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:
parent
8d22bf575c
commit
e2c977e95a
57
src/calc.c
57
src/calc.c
|
@ -141,18 +141,20 @@ static void adjustFont()
|
|||
int i = 0;
|
||||
int size = 0;
|
||||
while (displayed_code[i++]) {
|
||||
if(displayed_code[i] == '\n')
|
||||
if (displayed_code[i] == '\n') {
|
||||
size += 10;
|
||||
}
|
||||
size++;
|
||||
}
|
||||
// Use various system fonts for most text
|
||||
if (size <= 100) {
|
||||
int f = size < 50 ? smallestFont - 3 :
|
||||
const char* f = fonts[
|
||||
size < 50 ? smallestFont - 3 :
|
||||
size < 80 ? smallestFont - 2 :
|
||||
size < 100 ? smallestFont - 1 :
|
||||
smallestFont;
|
||||
text_layer_set_font(s_input_text_layer,
|
||||
fonts_get_system_font(fonts[f]));
|
||||
smallestFont
|
||||
];
|
||||
text_layer_set_font(s_input_text_layer, fonts_get_system_font(f));
|
||||
} else {
|
||||
// Use custom extra small font for lots of text
|
||||
text_layer_set_font(s_input_text_layer, tiny_font);
|
||||
|
@ -220,9 +222,11 @@ static void calculate()
|
|||
|
||||
stringNObj(temp, &obj, RESULT_LENGTH);
|
||||
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 {
|
||||
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);
|
||||
text_layer_set_text(s_result_text_layer, result_text);
|
||||
|
@ -301,16 +305,20 @@ static void code_window_load(Window *window)
|
|||
// Input text layer setup
|
||||
s_input_text_layer = text_layer_create(bounds);
|
||||
text_layer_set_text(s_input_text_layer, getToken(1));
|
||||
text_layer_set_font(s_input_text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_28_BOLD));
|
||||
layer_add_child(window_get_root_layer(s_code_window), text_layer_get_layer(s_input_text_layer));
|
||||
text_layer_set_font(s_input_text_layer,
|
||||
fonts_get_system_font(FONT_KEY_GOTHIC_28_BOLD));
|
||||
layer_add_child(window_get_root_layer(s_code_window),
|
||||
text_layer_get_layer(s_input_text_layer));
|
||||
|
||||
// Result text layer setup
|
||||
GRect result_bounds = GRect(6, 148, 132, 132);
|
||||
s_result_text_layer = text_layer_create(result_bounds);
|
||||
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);
|
||||
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'
|
||||
window_stack_push(s_code_window, true);
|
||||
|
@ -329,13 +337,16 @@ static void code_window_load(Window *window)
|
|||
#endif
|
||||
}
|
||||
|
||||
void debug_result(const char* d) {
|
||||
void debug_result(const char* d)
|
||||
{
|
||||
snprintf(result_text, RESULT_LENGTH, "%s", d);
|
||||
text_layer_set_text(s_result_text_layer, result_text);
|
||||
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;
|
||||
if (persist_exists(n)) {
|
||||
char* code = malloc(sizeof(char) * SMAX_LENGTH);
|
||||
|
@ -374,8 +385,8 @@ void code_window_push()
|
|||
|
||||
/** Menu Window **/
|
||||
|
||||
static void select_callback(struct MenuLayer *menu_layer,
|
||||
MenuIndex *cell_index, void *context)
|
||||
static void select_callback(MenuLayer* menu_layer, MenuIndex* cell_index,
|
||||
void* context)
|
||||
{
|
||||
current_script_num = cell_index->row;
|
||||
code_window_push();
|
||||
|
@ -397,7 +408,7 @@ static void draw_row_callback(GContext *ctx, const Layer *cell_layer,
|
|||
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)
|
||||
{
|
||||
return CELL_HEIGHT;
|
||||
|
@ -412,8 +423,11 @@ static void script_menu_load(Window *window)
|
|||
menu_layer_set_click_config_onto_window(s_script_select_layer, window);
|
||||
|
||||
#if defined(PBL_COLOR)
|
||||
menu_layer_set_normal_colors(s_script_select_layer, GColorBlack, GColorWhite);
|
||||
menu_layer_set_highlight_colors(s_script_select_layer, GColorDukeBlue, GColorWhite);
|
||||
menu_layer_set_normal_colors(s_script_select_layer,
|
||||
GColorBlack, GColorWhite);
|
||||
|
||||
menu_layer_set_highlight_colors(s_script_select_layer,
|
||||
GColorDukeBlue, GColorWhite);
|
||||
#endif
|
||||
|
||||
menu_layer_set_callbacks(s_script_select_layer, NULL, (MenuLayerCallbacks) {
|
||||
|
@ -422,6 +436,7 @@ static void script_menu_load(Window *window)
|
|||
.get_cell_height = get_cell_height_callback,
|
||||
.select_click = select_callback,
|
||||
});
|
||||
|
||||
layer_add_child(window_layer, menu_layer_get_layer(s_script_select_layer));
|
||||
}
|
||||
|
||||
|
@ -461,7 +476,8 @@ Object add_window(Object obj1, Object _, struct Environment *env)
|
|||
s_custom_window = window_create();
|
||||
WindowHandlers wh = {
|
||||
.load = custom_load,
|
||||
.unload = custom_unload };
|
||||
.unload = custom_unload
|
||||
};
|
||||
window_set_window_handlers(s_custom_window, wh);
|
||||
}
|
||||
|
||||
|
@ -470,7 +486,8 @@ Object add_window(Object obj1, Object _, struct Environment *env)
|
|||
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) {
|
||||
if (!s_code_window) {
|
||||
|
|
59
src/env.c
59
src/env.c
|
@ -1,19 +1,16 @@
|
|||
#include "env.h"
|
||||
#include "pebblisp.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef STANDALONE
|
||||
#include <pebble.h>
|
||||
#undef printf
|
||||
#define printf(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__)
|
||||
#endif
|
||||
#include "pebblisp.h"
|
||||
|
||||
Object fetchFromEnvironment(const char* name, struct Environment* env)
|
||||
{
|
||||
if(!env)
|
||||
if (!env) {
|
||||
return errorObject(NULL_ENV);
|
||||
}
|
||||
|
||||
if (env->size == 0) {
|
||||
if (env->outer) {
|
||||
|
@ -50,15 +47,14 @@ struct Environment envForLambda(const Object *params, const Object *arg_forms,
|
|||
{
|
||||
int paramCount = listLength(params);
|
||||
|
||||
struct Environment env = {
|
||||
.outer = outer,
|
||||
struct Environment env = {.outer = outer,
|
||||
.strings = NULL,
|
||||
.objects = NULL,
|
||||
.size = paramCount
|
||||
};
|
||||
.size = paramCount};
|
||||
|
||||
if(paramCount == 0)
|
||||
if (paramCount == 0) {
|
||||
return env;
|
||||
}
|
||||
|
||||
env.strings = calloc(sizeof(char*), paramCount + 1);
|
||||
env.objects = malloc(sizeof(Object) * (paramCount + 1));
|
||||
|
@ -119,7 +115,8 @@ void addToEnv(struct Environment *env, const char *name, const Object obj)
|
|||
// Add *new* item to env only if we're in the local scope
|
||||
if (temp_env->strings[i] == NULL) {
|
||||
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));
|
||||
temp_env->objects[i] = cloneObject(obj);
|
||||
return;
|
||||
|
@ -170,7 +167,8 @@ void printEnv(struct Environment *env)
|
|||
}
|
||||
}
|
||||
|
||||
void addFunc(const char *name, Object (*func)(Object, Object, struct Environment*),
|
||||
void addFunc(const char* name,
|
||||
Object (* func)(Object, Object, struct Environment*),
|
||||
struct Environment* env)
|
||||
{
|
||||
Object o = newObject(TYPE_FUNC);
|
||||
|
@ -197,6 +195,7 @@ void deleteEnv(struct Environment *e)
|
|||
|
||||
struct symFunc {
|
||||
const char* sym;
|
||||
|
||||
Object (* func)(Object, Object, struct Environment*);
|
||||
};
|
||||
|
||||
|
@ -214,20 +213,36 @@ struct Environment defaultEnv()
|
|||
};
|
||||
|
||||
struct symFunc symFuncs[] = {
|
||||
{"+", &add}, {"-", &sub}, {"*", &mul}, {"/", &dvi}, {"%", &mod},
|
||||
{"=", &equ}, {">", >h}, {"<", <h},
|
||||
{"cat", &catObjects}, {"fil", &filter}, {"len", &len},
|
||||
{"ap", &append}, {"pre", &prepend},
|
||||
{"at", &at}, {"rest", &rest},
|
||||
{"+", &add},
|
||||
{"-", &sub},
|
||||
{"*", &mul},
|
||||
{"/", &dvi},
|
||||
{"%", &mod},
|
||||
{"=", &equ},
|
||||
{">", >h},
|
||||
{"<", <h},
|
||||
{"&", &and},
|
||||
{"|", &or},
|
||||
{"cat", &catObjects},
|
||||
{"fil", &filter},
|
||||
{"len", &len},
|
||||
{"ap", &append},
|
||||
{"pre", &prepend},
|
||||
{"at", &at},
|
||||
{"rest", &rest},
|
||||
{"chat", &charAt},
|
||||
#ifndef LOW_MEM
|
||||
{"rev", &reverse},
|
||||
#endif
|
||||
{"isnum", &isNum}, {"isstr", &isString}, {"iserr", &isErr},
|
||||
{"isnum", &isNum},
|
||||
{"isstr", &isString},
|
||||
{"iserr", &isErr},
|
||||
{"char", &charVal},
|
||||
{"eval", &parseEvalO},
|
||||
#ifdef STANDALONE
|
||||
{"prn", &print}, {"pch", &pChar}, {"penv", &printEnvO},
|
||||
{"prn", &print},
|
||||
{"pch", &pChar},
|
||||
{"penv", &printEnvO},
|
||||
{"sys", &systemCall},
|
||||
{"loadfile", &loadFile},
|
||||
{"inp", &takeInput},
|
||||
|
|
11
src/env.h
11
src/env.h
|
@ -8,17 +8,24 @@ struct Environment {
|
|||
char** strings;
|
||||
Object* objects;
|
||||
struct Environment* outer;
|
||||
char size;
|
||||
int size;
|
||||
};
|
||||
|
||||
Object fetchFromEnvironment(const char* name, struct Environment* env);
|
||||
|
||||
struct Environment envForLambda(const Object* params, const Object* arg_forms,
|
||||
struct Environment* outer);
|
||||
|
||||
void addToEnv(struct Environment* env, const char* name, const Object obj);
|
||||
|
||||
void printEnv(struct Environment* env);
|
||||
void addFunc(const char *name, Object (*func)(Object, Object, struct Environment*),
|
||||
|
||||
void addFunc(const char* name,
|
||||
Object (* func)(Object, Object, struct Environment*),
|
||||
struct Environment* env);
|
||||
|
||||
void deleteEnv(struct Environment* e);
|
||||
|
||||
struct Environment defaultEnv();
|
||||
|
||||
#endif
|
||||
|
|
126
src/object.c
126
src/object.c
|
@ -1,20 +1,7 @@
|
|||
#include "object.h"
|
||||
#include <string.h>
|
||||
|
||||
#include <stdio.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
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* Returns the length of a given list Object
|
||||
|
@ -23,11 +10,14 @@
|
|||
*/
|
||||
int listLength(const Object* listObj)
|
||||
{
|
||||
if(!listObj || !isListy(*listObj))
|
||||
if (!listObj || !isListy(*listObj)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int len = 0;
|
||||
FOR_POINTER_IN_LIST(listObj) { len++; }
|
||||
FOR_POINTER_IN_LIST(listObj) {
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -48,15 +38,18 @@ Object len(Object obj1, Object o_ignore, struct Environment *e_ignore)
|
|||
*/
|
||||
Object* itemAt(const Object* listObj, int n)
|
||||
{
|
||||
if(!listObj || !isListy(*listObj))
|
||||
if (!listObj || !isListy(*listObj)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FOR_POINTER_IN_LIST(listObj) {
|
||||
if(POINTER == NULL)
|
||||
if (POINTER == NULL) {
|
||||
return NULL;
|
||||
if(n-- == 0)
|
||||
}
|
||||
if (n-- == 0) {
|
||||
return POINTER;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -67,8 +60,9 @@ Object *itemAt(const Object *listObj, int n)
|
|||
*/
|
||||
Object* tail(const Object* listObj)
|
||||
{
|
||||
if(!listObj || !isListy(*listObj))
|
||||
if (!listObj || !isListy(*listObj)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Object* tail = NULL;
|
||||
FOR_POINTER_IN_LIST(listObj) {
|
||||
|
@ -88,8 +82,9 @@ Object *tail(const Object *listObj)
|
|||
*/
|
||||
inline int isEmpty(const Object* obj)
|
||||
{
|
||||
if(obj == NULL)
|
||||
if (obj == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (obj->type) {
|
||||
case TYPE_NUMBER:
|
||||
|
@ -140,8 +135,9 @@ void allocObject(Object **spot, const Object src)
|
|||
*/
|
||||
void insertIntoList(Object* dest, int ind, const Object src)
|
||||
{
|
||||
if(!dest || !isListy(*dest))
|
||||
if (!dest || !isListy(*dest)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Merely append, when possible
|
||||
if (ind >= listLength(dest)) {
|
||||
|
@ -169,8 +165,9 @@ void insertIntoList(Object *dest, int ind, const Object src)
|
|||
*/
|
||||
void replaceListing(Object* list, int i, const Object src)
|
||||
{
|
||||
if(!list || isListy(*list))
|
||||
if (!list || isListy(*list)) {
|
||||
return;
|
||||
}
|
||||
Object* replace = itemAt(list, i);
|
||||
Object* oldForward = replace->forward;
|
||||
cleanObject(replace);
|
||||
|
@ -186,8 +183,9 @@ void replaceListing(Object *list, int i, const Object src)
|
|||
*/
|
||||
void nf_addToList(Object* dest, const Object src)
|
||||
{
|
||||
if(!dest || !isListy(*dest))
|
||||
if (!dest || !isListy(*dest)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isEmpty(dest)) {
|
||||
allocObject(&dest->list, src);
|
||||
|
@ -198,8 +196,7 @@ void nf_addToList(Object *dest, const Object src)
|
|||
}
|
||||
|
||||
#ifndef SIMPLE_ERRORS
|
||||
static const char *errorText[] = {
|
||||
"MISMATCHED_PARENS",
|
||||
static const char* errorText[] = {"MISMATCHED_PARENS",
|
||||
"BAD_LIST_OF_SYMBOL_STRINGS",
|
||||
"TYPE_LIST_NOT_CAUGHT",
|
||||
"NULL_ENV",
|
||||
|
@ -222,8 +219,7 @@ static const char *errorText[] = {
|
|||
"NO_CLONE_SPECIFIED",
|
||||
"CAN_ONLY_EVAL_STRINGS",
|
||||
"UNEXPECTED_EOF",
|
||||
"INDEX_PAST_END"
|
||||
};
|
||||
"INDEX_PAST_END"};
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -235,8 +231,9 @@ static const char *errorText[] = {
|
|||
*/
|
||||
void stringList(char* dest, const Object* obj)
|
||||
{
|
||||
if(!dest || !isListy(*obj))
|
||||
if (!dest || !isListy(*obj)) {
|
||||
return;
|
||||
}
|
||||
|
||||
dest[0] = '(';
|
||||
dest[1] = '\0';
|
||||
|
@ -266,9 +263,11 @@ void stringList(char *dest, const Object *obj)
|
|||
* @param dest The string to copy the list text into
|
||||
* @param obj The list Object to make a string from
|
||||
*/
|
||||
char* stringNObj(char *dest, const Object *obj, const size_t len) {
|
||||
if(!dest || !obj)
|
||||
char* stringNObj(char* dest, const Object* obj, const size_t len)
|
||||
{
|
||||
if (!dest || !obj) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (obj->type) {
|
||||
case TYPE_NUMBER:
|
||||
|
@ -293,8 +292,8 @@ char* stringNObj(char *dest, const Object *obj, const size_t len) {
|
|||
snprintf(dest, len, "E[%d]", (int)code);
|
||||
#else
|
||||
if (obj->error->context && obj->error->context[0] != '\0') {
|
||||
snprintf(dest, len, "'%s': %s",
|
||||
errorText[code], obj->error->context);
|
||||
snprintf(dest, len, "'%s': %s", errorText[code],
|
||||
obj->error->context);
|
||||
} else {
|
||||
snprintf(dest, len, "%s", errorText[code]);
|
||||
}
|
||||
|
@ -310,13 +309,15 @@ char* stringNObj(char *dest, const Object *obj, const size_t len) {
|
|||
break;
|
||||
}
|
||||
|
||||
if(!isValidType(*obj))
|
||||
if (!isValidType(*obj)) {
|
||||
snprintf(dest, len, "BAD_TYPE(%d) X%d", obj->type, obj->number);
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
char* stringObj(char *dest, const Object *obj) {
|
||||
char* stringObj(char* dest, const Object* obj)
|
||||
{
|
||||
return stringNObj(dest, obj, RESULT_LENGTH);
|
||||
}
|
||||
|
||||
|
@ -333,6 +334,7 @@ void debugObj(const Object *obj)
|
|||
}
|
||||
|
||||
#if defined(DEBUG) || defined(STANDALONE)
|
||||
|
||||
void printType(const Object* obj)
|
||||
{
|
||||
switch (obj->type) {
|
||||
|
@ -367,11 +369,13 @@ void printType(const Object *obj)
|
|||
return;
|
||||
}
|
||||
|
||||
if(!isValidType(*obj))
|
||||
if (!isValidType(*obj)) {
|
||||
printf("UNKNOWN TYPE (%d)", obj->type);
|
||||
}
|
||||
}
|
||||
|
||||
void nestedPrintList(const Object* list, int newline);
|
||||
|
||||
void _printList(const Object *list, int newline);
|
||||
void _printObj(const Object* obj, int newline)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
|
@ -387,11 +391,12 @@ void _printObj(const Object *obj, int newline)
|
|||
|
||||
char temp[100] = "";
|
||||
stringObj(temp, obj);
|
||||
if(newline)
|
||||
if (newline) {
|
||||
printf("%s\n", temp);
|
||||
else
|
||||
} else {
|
||||
printf("%s", temp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the given Object and a newline.
|
||||
|
@ -404,18 +409,21 @@ inline void printObj(const Object *obj)
|
|||
_printObj(obj, 1);
|
||||
}
|
||||
|
||||
void _printList(const Object *list, int newline)
|
||||
void nestedPrintList(const Object* list, int newline)
|
||||
{
|
||||
printf("(");
|
||||
if (list && isListy(*list)) {
|
||||
FOR_POINTER_IN_LIST(list) {
|
||||
printf(" ");
|
||||
_printObj(POINTER, 0);
|
||||
}
|
||||
}
|
||||
printf(" )");
|
||||
|
||||
if(newline)
|
||||
if (newline) {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints each Object in a given list, surrounded by parentheses
|
||||
|
@ -423,8 +431,9 @@ void _printList(const Object *list, int newline)
|
|||
*/
|
||||
void printList(const Object* list)
|
||||
{
|
||||
_printList(list, 1);
|
||||
nestedPrintList(list, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -439,8 +448,9 @@ void printList(const Object *list)
|
|||
*/
|
||||
void cleanObject(Object* target)
|
||||
{
|
||||
if(target == NULL)
|
||||
if (target == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (target->type) {
|
||||
case TYPE_STRING:
|
||||
|
@ -483,11 +493,13 @@ void cleanObject(Object *target)
|
|||
* @param target The object to print and clean
|
||||
*/
|
||||
#ifdef STANDALONE
|
||||
|
||||
void printAndClean(Object* target)
|
||||
{
|
||||
printObj(target);
|
||||
cleanObject(target);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -498,8 +510,9 @@ void printAndClean(Object *target)
|
|||
*/
|
||||
void deleteList(Object* dest)
|
||||
{
|
||||
if(!dest)
|
||||
if (!dest) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isListy(*dest)) {
|
||||
printf("Tried to delete something other than a list\n");
|
||||
|
@ -527,8 +540,9 @@ void _copyList(Object *dest, const Object *src, int delete)
|
|||
return;
|
||||
}
|
||||
|
||||
if(delete)
|
||||
if (delete) {
|
||||
deleteList(dest);
|
||||
}
|
||||
|
||||
FOR_POINTER_IN_LIST(src) {
|
||||
if (isListy(*POINTER)) {
|
||||
|
@ -654,10 +668,9 @@ inline Object cloneList(const Object src)
|
|||
return list;
|
||||
}
|
||||
|
||||
inline Object cloneOther(const Object src) {
|
||||
return src.other->clone?
|
||||
src.other->clone(src.other) :
|
||||
src;
|
||||
inline Object cloneOther(const Object src)
|
||||
{
|
||||
return src.other->clone ? src.other->clone(src.other) : src;
|
||||
}
|
||||
|
||||
inline Object cloneObject(const Object src)
|
||||
|
@ -677,7 +690,7 @@ inline Object cloneObject(const Object src)
|
|||
case TYPE_NUMBER:
|
||||
case TYPE_FUNC:
|
||||
case TYPE_OTHER:
|
||||
; // Fall through to plain return
|
||||
return src;
|
||||
}
|
||||
|
||||
return src;
|
||||
|
@ -720,11 +733,13 @@ inline Object symFromSlice(const char *string, int len)
|
|||
|
||||
inline Object constructLambda(const Object* params, const Object* body)
|
||||
{
|
||||
if(!params || !body)
|
||||
if (!params || !body) {
|
||||
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);
|
||||
}
|
||||
|
||||
Object o = newObject(TYPE_LAMBDA);
|
||||
o.lambda = malloc(sizeof(struct Lambda));
|
||||
|
@ -786,6 +801,7 @@ inline enum errorCode getErrorCode(const Object obj)
|
|||
}
|
||||
|
||||
#ifndef SIMPLE_ERRORS
|
||||
|
||||
inline void errorAddContext(Object* o, const char* context)
|
||||
{
|
||||
// printf("o: %p\n", o);
|
||||
|
@ -803,6 +819,7 @@ inline Object errorWithContext(enum errorCode code, const char* context)
|
|||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct Error noError()
|
||||
|
@ -814,7 +831,8 @@ struct Error noError()
|
|||
|
||||
inline Object toBool(const Object test)
|
||||
{
|
||||
if(test.number == 0)
|
||||
if (test.number == 0) {
|
||||
return boolObject(0);
|
||||
}
|
||||
return boolObject(1);
|
||||
}
|
||||
|
|
63
src/object.h
63
src/object.h
|
@ -3,19 +3,30 @@
|
|||
|
||||
#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_ENV_ELM 100
|
||||
#define RESULT_LENGTH 128
|
||||
|
||||
#define FOR_POINTER_IN_LIST(_list) \
|
||||
if(_list && isListy(*_list)) \
|
||||
for(Object *_element = _list->list; \
|
||||
for(Object *_element = (_list)->list; \
|
||||
_element != NULL;\
|
||||
_element = _element->forward)
|
||||
#define POINTER _element
|
||||
|
||||
#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 = _element->forward, _element2 = _element2->forward)
|
||||
#define P1 POINTER
|
||||
|
@ -82,11 +93,14 @@ struct Error {
|
|||
struct Object {
|
||||
Type type;
|
||||
Object *forward;
|
||||
|
||||
union {
|
||||
int number;
|
||||
Object *list;
|
||||
char *string;
|
||||
|
||||
Object (*func)(Object, Object, struct Environment *);
|
||||
|
||||
struct Lambda *lambda;
|
||||
struct Other *other;
|
||||
#ifdef SIMPLE_ERRORS
|
||||
|
@ -104,66 +118,109 @@ struct Lambda {
|
|||
|
||||
struct Other {
|
||||
void (*cleanup)(Object *);
|
||||
|
||||
Object (*clone)(struct Other *);
|
||||
|
||||
void *data;
|
||||
};
|
||||
|
||||
char *stringNObj(char *dest, const Object *obj, size_t len);
|
||||
|
||||
char *stringObj(char *dest, const Object *obj);
|
||||
|
||||
void printList(const Object *list);
|
||||
|
||||
void printType(const Object *obj);
|
||||
|
||||
void printObj(const Object *obj);
|
||||
|
||||
void _printObj(const Object *obj, int newline);
|
||||
|
||||
void debugObj(const Object *obj);
|
||||
|
||||
void printErr(const Object *obj);
|
||||
|
||||
int isEmpty(const Object *obj);
|
||||
|
||||
Object *tail(const Object *listObj);
|
||||
|
||||
void insertIntoList(Object *dest, int ind, const Object src);
|
||||
|
||||
void replaceListing(Object *list, int i, const Object src);
|
||||
|
||||
void nf_addToList(Object *dest, Object src);
|
||||
|
||||
void deleteList(Object *dest);
|
||||
|
||||
int listLength(const Object *listObj);
|
||||
|
||||
Object *itemAt(const Object *listObj, int n);
|
||||
|
||||
void copyList(Object *dest, const Object *src);
|
||||
|
||||
void cleanObject(Object *target);
|
||||
|
||||
void printAndClean(Object *target);
|
||||
|
||||
void allocObject(Object **spot, const Object src);
|
||||
|
||||
void appendList(Object *dest, const Object *src);
|
||||
|
||||
int isListy(const Object test);
|
||||
|
||||
int isStringy(const Object test);
|
||||
|
||||
int isValidType(const Object test);
|
||||
|
||||
int isError(const Object obj, const enum errorCode err);
|
||||
|
||||
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 areSameType(const Object *obj1, const Object *obj2);
|
||||
|
||||
Object cloneList(const Object src);
|
||||
|
||||
Object cloneString(Object obj);
|
||||
|
||||
Object cloneLambda(const Object old);
|
||||
|
||||
Object cloneObject(const Object src);
|
||||
|
||||
Object newObject(Type type);
|
||||
|
||||
Object listObject();
|
||||
|
||||
Object startList(const Object start);
|
||||
|
||||
Object objFromSlice(const char *string, int len);
|
||||
|
||||
Object stringFromSlice(const char *string, int len);
|
||||
|
||||
Object symFromSlice(const char *string, int len);
|
||||
|
||||
Object boolObject(int b);
|
||||
|
||||
Object numberObject(int num);
|
||||
|
||||
Object otherObject();
|
||||
|
||||
Object errorObject(enum errorCode err);
|
||||
|
||||
enum errorCode getErrorCode(const Object obj);
|
||||
|
||||
#ifdef SIMPLE_ERRORS
|
||||
#define errorWithContext(code, context) errorObject(code)
|
||||
#define errorAddContext(x, y) ;
|
||||
#else
|
||||
|
||||
Object errorWithContext(enum errorCode err, const char *context);
|
||||
|
||||
void errorAddContext(Object *o, const char *context);
|
||||
|
||||
#endif
|
||||
|
||||
struct Error noError();
|
||||
|
||||
Object constructLambda(const Object *params, const Object *body);
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
#include "pebbleobject.h"
|
||||
|
||||
#include "calc.h"
|
||||
#include "object.h"
|
||||
|
||||
Object pebbleOther(
|
||||
enum PebbleType type,
|
||||
void* data,
|
||||
void (*cleanup)(Object*),
|
||||
Object pebbleOther(enum PebbleType type, void* data, void (* cleanup)(Object*),
|
||||
Object (* clone)(struct Other*))
|
||||
{
|
||||
struct Object o = otherObject();
|
||||
|
@ -28,30 +26,34 @@ enum PebbleType getPebbleType(const Object o1)
|
|||
return P_ERROR;
|
||||
}
|
||||
|
||||
struct PebbleObject* accessPebbleObject(Object obj) {
|
||||
struct PebbleObject* accessPebbleObject(Object obj)
|
||||
{
|
||||
if (getPebbleType(obj) != P_ERROR) {
|
||||
return obj.other->data;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
Object createWindow(Object o1, Object o2, struct Environment *env) {
|
||||
Object createWindow(Object o1, Object o2, struct Environment* env)
|
||||
{
|
||||
Window* window = window_create();
|
||||
WindowHandlers wh = {
|
||||
.load = custom_window_load,
|
||||
WindowHandlers wh = {.load = custom_window_load,
|
||||
.unload = custom_window_unload};
|
||||
window_set_window_handlers(window, wh);
|
||||
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? */
|
||||
if (getPebbleType(window) == WINDOW) {
|
||||
window_stack_remove(accessPebbleObject(window)->window, true);
|
||||
|
@ -60,7 +62,8 @@ Object deleteWindow(Object window, Object o2, struct Environment *env) {
|
|||
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) {
|
||||
window_stack_push(accessPebbleObject(window)->window, true);
|
||||
return boolObject(1);
|
||||
|
@ -68,7 +71,8 @@ Object pushWindow(Object window, Object o2, struct Environment *env) {
|
|||
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);
|
||||
stringObj(po->textLayer->text, &text);
|
||||
|
@ -78,11 +82,13 @@ Object updateTextLayer(Object textLayer, Object text, struct Environment *env) {
|
|||
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) {
|
||||
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);
|
||||
|
||||
struct PLTextLayer* textLayer = malloc(sizeof(struct PLTextLayer));
|
||||
|
@ -98,29 +104,33 @@ Object addTextLayer(Object window, Object text, struct Environment *env) {
|
|||
return pebbleOther(TEXT_LAYER, textLayer, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
Object subscription;
|
||||
struct Environment* subscriptionEnv;
|
||||
|
||||
static void subscriptionHandler(struct tm *tick_time, TimeUnits changed) {
|
||||
static void subscriptionHandler(struct tm* tick_time, TimeUnits changed)
|
||||
{
|
||||
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) {
|
||||
subscription = cloneObject(function);
|
||||
subscriptionEnv = env;
|
||||
int unit = time.type != TYPE_NUMBER ? MINUTE_UNIT :
|
||||
time.number == 1 ? SECOND_UNIT :
|
||||
time.number == 2 ? MINUTE_UNIT :
|
||||
time.number == 3 ? HOUR_UNIT :
|
||||
time.number == 4 ? DAY_UNIT :
|
||||
time.number == 5 ? MONTH_UNIT :
|
||||
time.number == 6 ? YEAR_UNIT :
|
||||
MINUTE_UNIT;
|
||||
int unit = time.type != TYPE_NUMBER ? MINUTE_UNIT
|
||||
: time.number == 1 ? SECOND_UNIT
|
||||
: time.number == 2 ? MINUTE_UNIT
|
||||
: time.number == 3 ? HOUR_UNIT
|
||||
: time.number == 4
|
||||
? DAY_UNIT
|
||||
: time.number ==
|
||||
5 ? MONTH_UNIT
|
||||
:
|
||||
time.number ==
|
||||
6 ? YEAR_UNIT
|
||||
: MINUTE_UNIT;
|
||||
tick_timer_service_subscribe(unit, subscriptionHandler);
|
||||
return boolObject(1);
|
||||
}
|
||||
return boolObject(0);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
#include <pebble.h>
|
||||
|
||||
#include "pebblisp.h"
|
||||
|
||||
enum PebbleType {
|
||||
WINDOW,
|
||||
TEXT_LAYER,
|
||||
P_ERROR
|
||||
WINDOW, TEXT_LAYER, P_ERROR
|
||||
};
|
||||
|
||||
struct PLTextLayer {
|
||||
|
@ -23,8 +22,13 @@ struct PebbleObject {
|
|||
};
|
||||
|
||||
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 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);
|
||||
|
|
121
src/pebblisp.c
121
src/pebblisp.c
|
@ -1,14 +1,12 @@
|
|||
#pragma ide diagnostic ignored "misc-no-recursion"
|
||||
|
||||
#include "pebblisp.h"
|
||||
#include "tokens.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef STANDALONE
|
||||
#undef printf
|
||||
#define printf(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__)
|
||||
#include <pebble.h>
|
||||
#endif
|
||||
#include "tokens.h"
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @return The symbol(s) defined
|
||||
*/
|
||||
Object evalDefArgs(
|
||||
const Object *symbol,
|
||||
const Object *value,
|
||||
struct Environment *env
|
||||
) {
|
||||
Object evalDefArgs(const Object* symbol, const Object* value,
|
||||
struct Environment* env)
|
||||
{
|
||||
const char* name = symbol->string;
|
||||
|
||||
// Handles multi-definitions
|
||||
if(bothAre(TYPE_LIST, symbol, value)
|
||||
&& listLength(symbol) == listLength(value)) {
|
||||
if (bothAre(TYPE_LIST, symbol, value) &&
|
||||
listLength(symbol) == listLength(value)) {
|
||||
FOR_POINTERS_IN_LISTS(symbol, value) {
|
||||
Object finalValue = eval(P2, env);
|
||||
addToEnv(env, P1->string, finalValue);
|
||||
|
@ -50,17 +46,15 @@ Object evalDefArgs(
|
|||
Object evalIfArgs(const Object* argForms, struct Environment* env)
|
||||
{
|
||||
Object condition = eval(argForms, env);
|
||||
Object result = condition.number ?
|
||||
eval(argForms->forward, env) :
|
||||
eval(argForms->forward->forward, env);
|
||||
Object result = condition.number ? eval(argForms->forward, env)
|
||||
: eval(argForms->forward->forward, env);
|
||||
cleanObject(&condition);
|
||||
return result;
|
||||
}
|
||||
|
||||
Object evalLambdaArgs(const Object* argForms)
|
||||
{
|
||||
return constructLambda(
|
||||
argForms, // Params
|
||||
return constructLambda(argForms, // Params
|
||||
argForms ? argForms->forward : NULL // Body
|
||||
);
|
||||
}
|
||||
|
@ -79,6 +73,7 @@ Object evalMapArgs(const Object *argForms, struct Environment *env)
|
|||
return errorObject(BAD_TYPE);
|
||||
}
|
||||
|
||||
if (inputList) {
|
||||
FOR_POINTER_IN_LIST(inputList) {
|
||||
// Create a new list for each element,
|
||||
// since lambda evaluation looks for a list
|
||||
|
@ -95,6 +90,7 @@ Object evalMapArgs(const Object *argForms, struct Environment *env)
|
|||
cleanObject(&tempList);
|
||||
cleanObject(&lambda_output);
|
||||
}
|
||||
}
|
||||
cleanObject(&lambda);
|
||||
|
||||
return outputList;
|
||||
|
@ -159,11 +155,8 @@ void evalForms(Object *destArr, const Object *start, struct Environment *env)
|
|||
* @param length Length of `list` - 1, to exclude the already-evaluated element
|
||||
* @param env The environment to evaluate in
|
||||
*/
|
||||
Object listEvalFunc(
|
||||
const Object *list,
|
||||
const Object *function,
|
||||
const int length,
|
||||
struct Environment *env)
|
||||
Object listEvalFunc(const Object* list, const Object* function,
|
||||
const int length, struct Environment* env)
|
||||
{
|
||||
if (length == 0) {
|
||||
return function->func(boolObject(0), boolObject(0), env);
|
||||
|
@ -175,8 +168,7 @@ Object listEvalFunc(
|
|||
Object func_result = rest[0];
|
||||
if (length == 1) {
|
||||
Object oneArg = errorObject(ONLY_ONE_ARGUMENT);
|
||||
func_result = function->func(
|
||||
func_result, oneArg, env);
|
||||
func_result = function->func(func_result, oneArg, env);
|
||||
// Return a partial function if more parameters are required
|
||||
// Otherwise, return the function result
|
||||
cleanObject(&rest[0]);
|
||||
|
@ -212,16 +204,11 @@ Object listEvalFunc(
|
|||
* @param remaining The first element after `lambda`
|
||||
* @param env The environment to evaluate in
|
||||
*/
|
||||
Object listEvalLambda(
|
||||
Object *lambda,
|
||||
const Object *remaining,
|
||||
struct Environment *env
|
||||
) {
|
||||
struct Environment newEnv = envForLambda(
|
||||
&lambda->lambda->params,
|
||||
remaining,
|
||||
env
|
||||
);
|
||||
Object listEvalLambda(Object* lambda, const Object* remaining,
|
||||
struct Environment* env)
|
||||
{
|
||||
struct Environment newEnv =
|
||||
envForLambda(&lambda->lambda->params, remaining, env);
|
||||
Object ret = eval(&lambda->lambda->body, &newEnv);
|
||||
|
||||
deleteEnv(&newEnv);
|
||||
|
@ -377,6 +364,11 @@ Object _basicOp(const Object *obj1, const Object *obj2, const char op,
|
|||
case '%':
|
||||
return numberObject(n1 % n2);
|
||||
|
||||
case '&':
|
||||
return boolObject(n1 != 0 && n2 != 0);
|
||||
case '|':
|
||||
return boolObject(n1 != 0 || n2 != 0);
|
||||
|
||||
case '=':
|
||||
if (bothAre(TYPE_STRING, obj1, obj2)) {
|
||||
return boolObject(!strcmp(obj1->string, obj2->string));
|
||||
|
@ -405,7 +397,8 @@ Object basicOp(const Object *obj1, const Object *obj2, const char op,
|
|||
if (lists == 0) {
|
||||
return _basicOp(obj1, obj2, op, env);
|
||||
|
||||
} else if(lists == 1) { // Single operand is applied to each element in list
|
||||
} else if (lists ==
|
||||
1) { // Single operand is applied to each element in list
|
||||
const Object* listObj = (obj1->type == TYPE_LIST) ? obj1 : obj2;
|
||||
const Object* singleObj = (obj1->type == TYPE_LIST) ? obj2 : obj1;
|
||||
|
||||
|
@ -433,17 +426,30 @@ Object basicOp(const Object *obj1, const Object *obj2, const char op,
|
|||
|
||||
#define BASIC_OP(_name, _char) \
|
||||
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(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
|
||||
|
||||
Object filter(Object obj1, Object obj2, struct Environment* env)
|
||||
|
@ -520,14 +526,12 @@ Object reverse(Object _list, Object ignore, struct Environment *ignore2)
|
|||
|
||||
Object isNum(Object test, Object ignore, struct Environment* ignore2)
|
||||
{
|
||||
return test.type == TYPE_NUMBER ?
|
||||
boolObject(1) : boolObject(0);
|
||||
return test.type == TYPE_NUMBER ? boolObject(1) : boolObject(0);
|
||||
}
|
||||
|
||||
Object isString(Object test, Object ignore, struct Environment* ignore2)
|
||||
{
|
||||
return test.type == TYPE_STRING ?
|
||||
boolObject(1) : boolObject(0);
|
||||
return test.type == TYPE_STRING ? boolObject(1) : boolObject(0);
|
||||
}
|
||||
|
||||
// Get the int value of a string's first character
|
||||
|
@ -540,8 +544,7 @@ Object charVal(Object test, Object ignore, struct Environment *ignore2)
|
|||
|
||||
Object isErr(Object test, Object ignore, struct Environment* ignore2)
|
||||
{
|
||||
return test.type == TYPE_ERROR ?
|
||||
boolObject(1) : boolObject(0);
|
||||
return test.type == TYPE_ERROR ? boolObject(1) : boolObject(0);
|
||||
}
|
||||
|
||||
Object charAt(Object string, Object at, struct Environment* ignore)
|
||||
|
@ -554,6 +557,7 @@ Object charAt(Object string, Object at, struct Environment *ignore)
|
|||
}
|
||||
|
||||
#ifdef STANDALONE
|
||||
|
||||
Object print(Object p, Object ignore, struct Environment* env)
|
||||
{
|
||||
p = cloneObject(p);
|
||||
|
@ -571,7 +575,8 @@ Object pChar(Object c, Object i1, struct Environment *i2)
|
|||
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;
|
||||
}
|
||||
|
@ -579,6 +584,7 @@ Object printEnvO(Object i1, Object i2, struct Environment *env) {
|
|||
printEnv(env);
|
||||
return numberObject(0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Object parseEvalO(Object text, Object ignore, struct Environment* env)
|
||||
|
@ -595,12 +601,14 @@ Object parseEvalO(Object text, Object ignore, struct Environment *env)
|
|||
}
|
||||
|
||||
#ifdef STANDALONE
|
||||
|
||||
Object takeInput(Object i1, Object i2, struct Environment* i3)
|
||||
{
|
||||
char input[256] = "";
|
||||
fgets(input, 256, stdin);
|
||||
return stringFromSlice(input, strlen(input) - 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void copySlice(char* dest, struct Slice* src)
|
||||
|
@ -806,10 +814,12 @@ Object parseEval(const char *input, struct Environment *env)
|
|||
}
|
||||
|
||||
#ifdef STANDALONE
|
||||
int _readFile(FILE *input, struct Environment *env) {
|
||||
|
||||
int _readFile(FILE* input, struct Environment* env)
|
||||
{
|
||||
Object r = numberObject(0);
|
||||
char page[4096] = "";
|
||||
const unsigned LINE_MAX = 256;
|
||||
const int LINE_MAX = 256;
|
||||
char line[LINE_MAX];
|
||||
if (fgets(line, LINE_MAX, input)) {
|
||||
if (line[0] != '#' || line[1] != '!') {
|
||||
|
@ -843,7 +853,9 @@ int _readFile(FILE *input, struct Environment *env) {
|
|||
fclose(input);
|
||||
return 0;
|
||||
}
|
||||
int readFile(const char *filename, struct Environment *env) {
|
||||
|
||||
int readFile(const char* filename, struct Environment* env)
|
||||
{
|
||||
FILE* input = fopen(filename, "r");
|
||||
if (!input) {
|
||||
return 1;
|
||||
|
@ -852,7 +864,8 @@ int readFile(const char *filename, struct Environment *env) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
Object loadFile(Object filename, Object _, struct Environment *env) {
|
||||
Object loadFile(Object filename, Object _, struct Environment* env)
|
||||
{
|
||||
if (isStringy(filename)) {
|
||||
readFile(filename.string, env);
|
||||
return numberObject(0);
|
||||
|
@ -860,21 +873,24 @@ Object loadFile(Object filename, Object _, struct Environment *env) {
|
|||
return numberObject(1);
|
||||
}
|
||||
|
||||
Object systemCall(Object process, Object _, struct Environment *env) {
|
||||
Object systemCall(Object process, Object _, struct Environment* env)
|
||||
{
|
||||
if (isStringy(process)) {
|
||||
return numberObject(system(process.string));
|
||||
}
|
||||
return numberObject(255);
|
||||
}
|
||||
|
||||
void repl(struct Environment *env) {
|
||||
void repl(struct Environment* env)
|
||||
{
|
||||
if (readFile(SCRIPTDIR "/repl.pbl", env) == 1) {
|
||||
fprintf(stderr, "Could not read '%s'\n", SCRIPTDIR "/repl.pbl");
|
||||
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();
|
||||
for (int i = 0; i < argc; i++) {
|
||||
nf_addToList(&args, stringFromSlice(argv[i], strlen(argv[i])));
|
||||
|
@ -907,4 +923,5 @@ int main(int argc, const char* argv[])
|
|||
}
|
||||
deleteEnv(&env);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,19 +1,8 @@
|
|||
#ifndef PEBBLISP_H
|
||||
#define PEBBLISP_H
|
||||
|
||||
#include "object.h"
|
||||
#include "env.h"
|
||||
|
||||
#ifndef STANDALONE
|
||||
#include <pebble.h>
|
||||
#define printd(...) ;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define printd(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define printd(...) ;
|
||||
#endif
|
||||
#include "object.h"
|
||||
|
||||
struct Slice {
|
||||
const char* text;
|
||||
|
@ -26,51 +15,91 @@ typedef struct Result {
|
|||
} Result;
|
||||
|
||||
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);
|
||||
|
||||
// Slices
|
||||
void copySlice(char* dest, struct Slice* src);
|
||||
|
||||
void debugSlice(struct Slice* s);
|
||||
|
||||
#define BASIC_OP(_name) \
|
||||
Object _name(Object obj1, Object obj2, struct Environment *env);
|
||||
BASIC_OP(add); BASIC_OP(sub);
|
||||
BASIC_OP(mul); BASIC_OP(dvi);
|
||||
BASIC_OP(mod); BASIC_OP(equ);
|
||||
BASIC_OP(gth); BASIC_OP(lth);
|
||||
|
||||
BASIC_OP(add);
|
||||
|
||||
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
|
||||
|
||||
Object catObjects(const Object obj1, const Object obj2, struct Environment *env);
|
||||
Object catObjects(const Object obj1, const Object obj2,
|
||||
struct Environment* env);
|
||||
|
||||
Object filter(Object obj1, Object obj2, 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 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
|
||||
|
||||
Object takeInput(Object i1, Object i2, struct Environment* i3);
|
||||
|
||||
Object systemCall(Object call, Object _, struct Environment* i3);
|
||||
|
||||
Object loadFile(Object filename, Object _, struct Environment* env);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
27
src/pebcom.c
27
src/pebcom.c
|
@ -1,29 +1,36 @@
|
|||
#include <pebble.h>
|
||||
#include "pebcom.h"
|
||||
|
||||
struct tm* getTime() {
|
||||
#include <pebble.h>
|
||||
|
||||
struct tm* getTime()
|
||||
{
|
||||
time_t t = time(NULL);
|
||||
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);
|
||||
}
|
||||
|
||||
Object getMinutes(Object o1, Object o2, struct Environment *env) {
|
||||
Object getMinutes(Object o1, Object o2, struct Environment* env)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
uint32_t pattern[length];
|
||||
if (length > 0) {
|
||||
|
@ -35,10 +42,8 @@ Object doVibe(Object patternList, Object o2, struct Environment *env) {
|
|||
}
|
||||
i++;
|
||||
}
|
||||
vibes_enqueue_custom_pattern((VibePattern) {
|
||||
.durations = pattern,
|
||||
.num_segments = length
|
||||
});
|
||||
vibes_enqueue_custom_pattern(
|
||||
(VibePattern) {.durations = pattern, .num_segments = length});
|
||||
return boolObject(1);
|
||||
} else {
|
||||
return errorObject(NOT_A_LIST);
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
#include "pebblisp.h"
|
||||
|
||||
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);
|
||||
|
|
41
src/tokens.c
41
src/tokens.c
|
@ -1,19 +1,8 @@
|
|||
#include "tokens.h"
|
||||
|
||||
#include <stdlib.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
|
||||
|
||||
/*
|
||||
|
@ -26,29 +15,36 @@
|
|||
|
||||
// Is the char a standalone token?
|
||||
static const char singleTokens[] = "()+-*/='";
|
||||
int isSingle(const char c) {
|
||||
|
||||
int isSingle(const char c)
|
||||
{
|
||||
int i = 0;
|
||||
while (singleTokens[i] != '\0') {
|
||||
if(singleTokens[i] == c)
|
||||
if (singleTokens[i] == c) {
|
||||
return singleTokens[i];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int isDigit(const char c) {
|
||||
int isDigit(const char c)
|
||||
{
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
int isHex(const char c) {
|
||||
int isHex(const char c)
|
||||
{
|
||||
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';
|
||||
}
|
||||
|
||||
int notWhitespace(const char c) {
|
||||
int notWhitespace(const char c)
|
||||
{
|
||||
return !isWhitespace(c);
|
||||
}
|
||||
|
||||
|
@ -106,10 +102,12 @@ struct Slice *nf_tokenize(const char *input, struct Error *err)
|
|||
slices[slice].text += 2;
|
||||
for (;;) {
|
||||
i++;
|
||||
if(input[i] == '"' && input[i + 1] == '"' && input[i + 2] == '"') {
|
||||
if (input[i] == '"' && input[i + 1] == '"' &&
|
||||
input[i + 2] == '"') {
|
||||
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->code = UNEXPECTED_EOF;
|
||||
int start = i > ERR_LEN ? i - ERR_LEN : 0;
|
||||
|
@ -126,7 +124,8 @@ struct Slice *nf_tokenize(const char *input, struct Error *err)
|
|||
}
|
||||
i++;
|
||||
} else {
|
||||
while(!isWhitespace(input[++i]) && !isSingle(input[i]) && input[i] != '\0') {
|
||||
while (!isWhitespace(input[++i]) && !isSingle(input[i]) &&
|
||||
input[i] != '\0') {
|
||||
l++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,11 @@
|
|||
#include "pebblisp.h"
|
||||
|
||||
int isSingle(const char c);
|
||||
|
||||
int isDigit(const char c);
|
||||
|
||||
int isHex(const char c);
|
||||
|
||||
struct Slice* nf_tokenize(const char* input, struct Error* err);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue