Replace (struct's field) with (struct.field)
It was cute, but hard to read in space-delimited lists. Convert (map) to a normal pl function. Add trueObject() falseObject() macros.
This commit is contained in:
parent
b4e0f57029
commit
32e21bf758
|
@ -12,15 +12,15 @@ mkfile_dir := $(dir $(mkfile_path))
|
||||||
GCC_ARGS ?= -g -Wall -o $(exe) -D WEBSERVER -D STANDALONE -DSCRIPTDIR=\"$(SCRIPTDIR)\"
|
GCC_ARGS ?= -g -Wall -o $(exe) -D WEBSERVER -D STANDALONE -DSCRIPTDIR=\"$(SCRIPTDIR)\"
|
||||||
GCC_COM ?= gcc -O0 $(GCC_ARGS)
|
GCC_COM ?= gcc -O0 $(GCC_ARGS)
|
||||||
|
|
||||||
all:
|
|
||||||
$(GCC_COM) $(file_libs) && echo && ./tests.sh
|
|
||||||
|
|
||||||
release:
|
release:
|
||||||
gcc -O3 $(GCC_ARGS) $(file_libs) && strip ./$(exe) && echo && ./tests.sh
|
gcc -O3 $(GCC_ARGS) $(file_libs) && strip ./$(exe) && echo && ./tests.sh
|
||||||
|
|
||||||
notest:
|
notest:
|
||||||
$(GCC_COM) $(file_libs)
|
$(GCC_COM) $(file_libs)
|
||||||
|
|
||||||
|
all: notest
|
||||||
|
echo && ./tests.sh
|
||||||
|
|
||||||
local:
|
local:
|
||||||
gcc -g -O0 -Wall -o $(exe) -D STANDALONE -DSCRIPTDIR=\"$(mkfile_dir)/examples\" $(file_libs)
|
gcc -g -O0 -Wall -o $(exe) -D STANDALONE -DSCRIPTDIR=\"$(mkfile_dir)/examples\" $(file_libs)
|
||||||
|
|
||||||
|
|
|
@ -412,6 +412,7 @@ struct Environment defaultEnv()
|
||||||
pf(append),
|
pf(append),
|
||||||
pf(prepend),
|
pf(prepend),
|
||||||
pf(reduce),
|
pf(reduce),
|
||||||
|
pf(mapO),
|
||||||
pf(at),
|
pf(at),
|
||||||
pf(rest),
|
pf(rest),
|
||||||
pf(charAt),
|
pf(charAt),
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
(def reload (fn () (loadfile (cat (env "HOME") "/.pebblisp.pbl"))))
|
(def reload (fn () (loadfile (cat (env "HOME") "/.pebblisp.pbl"))))
|
||||||
|
|
||||||
(def hour (fn (ti) (
|
(def hour (fn (ti) (
|
||||||
(def h (% ti's hour 12))
|
(def h (% ti.hour 12))
|
||||||
(if (= 0 h) 12 h)
|
(if (= 0 h) 12 h)
|
||||||
)))
|
)))
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
(def zero (fn (num) (cat (if (< num 10) "0" "") num)))
|
(def zero (fn (num) (cat (if (< num 10) "0" "") num)))
|
||||||
|
|
||||||
(def clock (fn (ti) (cat (hour ti) ":" (zero ti's minute) ":" (zero ti's sec))))
|
(def clock (fn (ti) (cat (hour ti) ":" (zero ti.minute) ":" (zero ti.sec))))
|
||||||
|
|
||||||
(def prompt (fn (a) (
|
(def prompt (fn (a) (
|
||||||
(def ti (time))
|
(def ti (time))
|
||||||
|
|
|
@ -701,7 +701,7 @@ inline Object symFromSlice(const char* string, int len)
|
||||||
|
|
||||||
/// Creates a stringy object with room for a reference-count prefix and trailing null byte.
|
/// Creates a stringy object with room for a reference-count prefix and trailing null byte.
|
||||||
/// Thus, withLen(3, TYPE_STRING) will actually allocate a 5-byte "string".
|
/// Thus, withLen(3, TYPE_STRING) will actually allocate a 5-byte "string".
|
||||||
inline Object withLen(int len, enum Type type)
|
inline Object withLen(size_t len, enum Type type)
|
||||||
{
|
{
|
||||||
Object o = newObject(type);
|
Object o = newObject(type);
|
||||||
o.string = malloc(sizeof(char) * (len + 2));
|
o.string = malloc(sizeof(char) * (len + 2));
|
||||||
|
|
|
@ -206,7 +206,7 @@ Object stringFromSlice(const char* string, int len);
|
||||||
|
|
||||||
Object symFromSlice(const char* string, int len);
|
Object symFromSlice(const char* string, int len);
|
||||||
|
|
||||||
Object withLen(int len, enum Type type);
|
Object withLen(size_t len, enum Type type);
|
||||||
|
|
||||||
Object boolObject(int b);
|
Object boolObject(int b);
|
||||||
|
|
||||||
|
|
|
@ -57,18 +57,18 @@ 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 trueObject();
|
||||||
}
|
}
|
||||||
return boolObject(0);
|
return falseObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
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 trueObject();
|
||||||
}
|
}
|
||||||
return boolObject(0);
|
return falseObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object updateTextLayer(Object textLayer, Object text, struct Environment* env)
|
Object updateTextLayer(Object textLayer, Object text, struct Environment* env)
|
||||||
|
@ -77,9 +77,9 @@ Object updateTextLayer(Object textLayer, Object text, struct Environment* env)
|
||||||
struct PebbleObject* po = accessPebbleObject(textLayer);
|
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 trueObject();
|
||||||
}
|
}
|
||||||
return boolObject(0);
|
return falseObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object addTextLayer(Object window, Object text, struct Environment* env)
|
Object addTextLayer(Object window, Object text, struct Environment* env)
|
||||||
|
@ -130,7 +130,7 @@ Object subscribe(Object function, Object time, struct Environment* env)
|
||||||
6 ? YEAR_UNIT
|
6 ? YEAR_UNIT
|
||||||
: MINUTE_UNIT;
|
: MINUTE_UNIT;
|
||||||
tick_timer_service_subscribe(unit, subscriptionHandler);
|
tick_timer_service_subscribe(unit, subscriptionHandler);
|
||||||
return boolObject(1);
|
return trueObject();
|
||||||
}
|
}
|
||||||
return boolObject(0);
|
return falseObject();
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,8 @@ Object def(Object* params, int length, struct Environment* env)
|
||||||
/**
|
/**
|
||||||
* Add a struct to the environment with a given name and fields.
|
* Add a struct to the environment with a given name and fields.
|
||||||
*
|
*
|
||||||
|
* Not a typical pl function because I don't feel like adding more syntactic sugar right now.
|
||||||
|
*
|
||||||
* (struct point (x y))
|
* (struct point (x y))
|
||||||
*/
|
*/
|
||||||
Object evalStructArgs(const Object* symbol, const Object* fields, struct Environment* env)
|
Object evalStructArgs(const Object* symbol, const Object* fields, struct Environment* env)
|
||||||
|
@ -66,20 +68,21 @@ Object evalStructArgs(const Object* symbol, const Object* fields, struct Environ
|
||||||
def.fieldCount = listLength(fields);
|
def.fieldCount = listLength(fields);
|
||||||
def.names = malloc(sizeof(char*) * def.fieldCount);
|
def.names = malloc(sizeof(char*) * def.fieldCount);
|
||||||
|
|
||||||
{
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
FOR_POINTER_IN_LIST(fields) {
|
FOR_POINTER_IN_LIST(fields) {
|
||||||
def.names[i] = malloc(sizeof(char) * (strlen(POINTER->string) + 1));
|
def.names[i] = malloc(sizeof(char) * (strlen(POINTER->string) + 1));
|
||||||
strcpy(def.names[i], POINTER->string);
|
strcpy(def.names[i], POINTER->string);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
addStructDef(def);
|
addStructDef(def);
|
||||||
|
|
||||||
return boolObject(1);
|
return trueObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not a typical pl function because delayed evaluation is annoying in those right now.
|
||||||
|
*/
|
||||||
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);
|
||||||
|
@ -89,19 +92,22 @@ Object evalIfArgs(const Object* argForms, struct Environment* env)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not a typical pl function because it relies almost exclusively on symbols
|
||||||
|
*/
|
||||||
Object evalLambdaArgs(const Object* argForms, struct Environment* env)
|
Object evalLambdaArgs(const Object* argForms, struct Environment* env)
|
||||||
{
|
{
|
||||||
return constructLambda(argForms, argForms ? argForms->forward : NULL, env);
|
return constructLambda(argForms, argForms ? argForms->forward : NULL, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object evalMapArgs(const Object* argForms, struct Environment* env)
|
Object mapO(Object* params, int length, struct Environment* env)
|
||||||
{
|
{
|
||||||
if (!argForms) {
|
if (length < 2) {
|
||||||
return errorObject(NULL_MAP_ARGS);
|
return errorObject(NULL_MAP_ARGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object lambda = eval(argForms, env);
|
Object lambda = eval(¶ms[0], env);
|
||||||
const Object* inputList = argForms->forward;
|
const Object* inputList = ¶ms[1];
|
||||||
|
|
||||||
if (lambda.type != TYPE_LAMBDA) {
|
if (lambda.type != TYPE_LAMBDA) {
|
||||||
return errorObject(BAD_TYPE);
|
return errorObject(BAD_TYPE);
|
||||||
|
@ -114,8 +120,8 @@ Object evalMapArgs(const Object* argForms, struct Environment* env)
|
||||||
// since lambda evaluation looks for a list
|
// since lambda evaluation looks for a list
|
||||||
Object tempInput = cloneObject(*POINTER);
|
Object tempInput = cloneObject(*POINTER);
|
||||||
|
|
||||||
Object* params = &lambda.lambda->params;
|
Object* lambdaParams = &lambda.lambda->params;
|
||||||
struct Environment newEnv = envForLambda(params, &tempInput, listLength(params), env);
|
struct Environment newEnv = envForLambda(lambdaParams, &tempInput, listLength(lambdaParams), 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);
|
||||||
|
@ -137,8 +143,6 @@ Object evalBuiltIns(const Object* first, const Object* rest,
|
||||||
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, env);
|
return evalLambdaArgs(rest, env);
|
||||||
} else if (strcmp(first->string, "map") == 0) {
|
|
||||||
return evalMapArgs(rest, env);
|
|
||||||
} else if (strcmp(first->string, "struct") == 0) {
|
} else if (strcmp(first->string, "struct") == 0) {
|
||||||
return evalStructArgs(rest, rest->forward, env);
|
return evalStructArgs(rest, rest->forward, env);
|
||||||
}
|
}
|
||||||
|
@ -454,29 +458,27 @@ Result parseAtom(struct Slice* s)
|
||||||
return (Result) { parseBin(s), s };
|
return (Result) { parseBin(s), s };
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
return (Result) {errorObject(UNSUPPORTED_NUMBER_TYPE), s};
|
return (Result) { errorWithContext(UNSUPPORTED_NUMBER_TYPE, s->text), s };
|
||||||
}
|
}
|
||||||
} else if (s->length == 1 && (c == 'T' || c == 't')) {
|
} else if (s->length == 1 && c == 'T') {
|
||||||
return (Result) {boolObject(1), s};
|
return (Result) { trueObject(), s };
|
||||||
} else if (s->length == 1 && (c == 'F' || c == 'f')) {
|
} else if (s->length == 1 && c == 'F') {
|
||||||
return (Result) {boolObject(0), s};
|
return (Result) { falseObject(), s };
|
||||||
} else if (c == '"'/* || c == '\''*/) {
|
} else if (c == '"'/* || c == '\''*/) {
|
||||||
return (Result) { objFromSlice(s->text, s->length), s };
|
return (Result) { objFromSlice(s->text, s->length), s };
|
||||||
} else {
|
} else if (s->text[s->length] == '.') {
|
||||||
if (s->text[s->length] == '\'' && s->text[s->length + 1] == 's') {
|
|
||||||
Object possessiveFunc = newObject(TYPE_FUNC);
|
Object possessiveFunc = newObject(TYPE_FUNC);
|
||||||
possessiveFunc.func = &possessive;
|
possessiveFunc.func = &possessive;
|
||||||
Object list = startList(possessiveFunc);
|
Object list = startList(possessiveFunc);
|
||||||
Object possesser = symFromSlice(s->text, s->length);
|
Object possesser = symFromSlice(s->text, s->length);
|
||||||
nf_addToList(&list, possesser);
|
nf_addToList(&list, possesser);
|
||||||
struct Slice* next = s + 3;
|
struct Slice* next = s + 2;
|
||||||
Object possessed = objFromSlice(&next->text[-1], next->length + 1);
|
Object possessed = objFromSlice(&next->text[-1], next->length + 1);
|
||||||
nf_addToList(&list, possessed);
|
nf_addToList(&list, possessed);
|
||||||
return (Result) { list, next };
|
return (Result) { list, next };
|
||||||
}
|
}
|
||||||
return (Result) { symFromSlice(s->text, s->length), s };
|
return (Result) { symFromSlice(s->text, s->length), s };
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
struct Slice* lastOpen = NULL;
|
struct Slice* lastOpen = NULL;
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,10 @@ fnn(_name, _docs, __VA_ARGS__)
|
||||||
static const char * const _name ## Symbol = _symbol; \
|
static const char * const _name ## Symbol = _symbol; \
|
||||||
fnn(_name, _docs, __VA_ARGS__)
|
fnn(_name, _docs, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define trueObject() boolObject(1)
|
||||||
|
|
||||||
|
#define falseObject() boolObject(0)
|
||||||
|
|
||||||
struct Slice {
|
struct Slice {
|
||||||
const char* text;
|
const char* text;
|
||||||
unsigned char length;
|
unsigned char length;
|
||||||
|
@ -68,6 +72,11 @@ int readFile(const char* filename, struct Environment* env);
|
||||||
|
|
||||||
#endif /* STANDALONE */
|
#endif /* STANDALONE */
|
||||||
|
|
||||||
|
fn(mapO, "map",
|
||||||
|
"Map over a list with a function.",
|
||||||
|
"(map (fn (a) (* a a)) (1 2 3))", "( 1 4 9 )",
|
||||||
|
);
|
||||||
|
|
||||||
fn(def, "def",
|
fn(def, "def",
|
||||||
"Define a variable in the current scope.",
|
"Define a variable in the current scope.",
|
||||||
"(def x 10) x", "10",
|
"(def x 10) x", "10",
|
||||||
|
|
|
@ -44,7 +44,7 @@ Object doVibe(Object patternList, Object o2, struct Environment* env)
|
||||||
}
|
}
|
||||||
vibes_enqueue_custom_pattern(
|
vibes_enqueue_custom_pattern(
|
||||||
(VibePattern) {.durations = pattern, .num_segments = length});
|
(VibePattern) {.durations = pattern, .num_segments = length});
|
||||||
return boolObject(1);
|
return trueObject();
|
||||||
} else {
|
} else {
|
||||||
return errorObject(NOT_A_LIST);
|
return errorObject(NOT_A_LIST);
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,7 +169,7 @@ Object isNum(Object* params, int length, struct Environment* env)
|
||||||
checkTypes(isNum)
|
checkTypes(isNum)
|
||||||
Object test = params[0];
|
Object test = params[0];
|
||||||
|
|
||||||
return test.type == TYPE_NUMBER ? boolObject(1) : boolObject(0);
|
return boolObject(test.type == TYPE_NUMBER);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object isList(Object* params, int length, struct Environment* env)
|
Object isList(Object* params, int length, struct Environment* env)
|
||||||
|
@ -177,7 +177,7 @@ Object isList(Object* params, int length, struct Environment* env)
|
||||||
checkTypes(isList)
|
checkTypes(isList)
|
||||||
Object test = params[0];
|
Object test = params[0];
|
||||||
|
|
||||||
return test.type == TYPE_LIST ? boolObject(1) : boolObject(0);
|
return boolObject(test.type == TYPE_LIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object isString(Object* params, int length, struct Environment* env)
|
Object isString(Object* params, int length, struct Environment* env)
|
||||||
|
@ -185,7 +185,7 @@ Object isString(Object* params, int length, struct Environment* env)
|
||||||
checkTypes(isString)
|
checkTypes(isString)
|
||||||
Object test = params[0];
|
Object test = params[0];
|
||||||
|
|
||||||
return test.type == TYPE_STRING ? boolObject(1) : boolObject(0);
|
return boolObject(test.type == TYPE_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object charVal(Object* params, int length, struct Environment* env)
|
Object charVal(Object* params, int length, struct Environment* env)
|
||||||
|
@ -201,7 +201,7 @@ Object isErr(Object* params, int length, struct Environment* env)
|
||||||
checkTypes(isErr)
|
checkTypes(isErr)
|
||||||
Object test = params[0];
|
Object test = params[0];
|
||||||
|
|
||||||
return test.type == TYPE_ERROR ? boolObject(1) : boolObject(0);
|
return boolObject(test.type == TYPE_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object parseEvalO(Object* params, int length, struct Environment* env)
|
Object parseEvalO(Object* params, int length, struct Environment* env)
|
||||||
|
|
|
@ -194,7 +194,7 @@ fn(possessive, "poss",
|
||||||
"Get the value of a struct's field",
|
"Get the value of a struct's field",
|
||||||
"(struct Post (title body))\n "
|
"(struct Post (title body))\n "
|
||||||
"(def p (Post \"TI\" \"BO\"))\n "
|
"(def p (Post \"TI\" \"BO\"))\n "
|
||||||
"p's title", "TI"
|
"p.title", "TI"
|
||||||
);
|
);
|
||||||
|
|
||||||
#ifdef STANDALONE
|
#ifdef STANDALONE
|
||||||
|
|
|
@ -205,7 +205,7 @@ check "Building a struct"\
|
||||||
'(struct Post (title body)) (Post "A title" "The Body")'\
|
'(struct Post (title body)) (Post "A title" "The Body")'\
|
||||||
'{ title: "A title", body: "The Body" }'
|
'{ title: "A title", body: "The Body" }'
|
||||||
check "Accessing struct fields"\
|
check "Accessing struct fields"\
|
||||||
"(struct Post (title body)) (def p (Post \"TITLE\" \"BODY\")) (p's title p's body)"\
|
"(struct Post (title body)) (def p (Post \"TITLE\" \"BODY\")) (p.title p.body)"\
|
||||||
"( TITLE BODY )"
|
"( TITLE BODY )"
|
||||||
|
|
||||||
title "HigherOrder"
|
title "HigherOrder"
|
||||||
|
@ -217,7 +217,7 @@ check "FuncReturningAFunc" "(def plusser (fn (outer) (fn (inner) (+ outer inner)
|
||||||
|
|
||||||
title "ShouldError"
|
title "ShouldError"
|
||||||
check "LenOfNotList" "(len 5)" regex "BAD_PARAMS_ON.*"
|
check "LenOfNotList" "(len 5)" regex "BAD_PARAMS_ON.*"
|
||||||
check "NoMapList" "(map sq)" "( )"
|
check "NoMapList" "(map sq)" "NULL_MAP_ARGS"
|
||||||
check "BadNumber" "(5df)" regex "BAD_NUMBER.*"
|
check "BadNumber" "(5df)" regex "BAD_NUMBER.*"
|
||||||
check "BadHex" "(0x0zf)" regex "BAD_NUMBER.*"
|
check "BadHex" "(0x0zf)" regex "BAD_NUMBER.*"
|
||||||
check "BadBinary" "(0b01120)" regex "BAD_NUMBER.*"
|
check "BadBinary" "(0b01120)" regex "BAD_NUMBER.*"
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// 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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue