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:
Sage Vaillancourt 2022-03-31 10:29:06 -04:00 committed by Sage Vaillancourt
parent b4e0f57029
commit 32e21bf758
13 changed files with 76 additions and 64 deletions

View File

@ -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)

View File

@ -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),

View File

@ -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))

View File

@ -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));

View File

@ -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);

View File

@ -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();
} }

View File

@ -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(&params[0], env);
const Object* inputList = argForms->forward; const Object* inputList = &params[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);
} }
@ -358,7 +362,7 @@ Result parse(struct Slice* slices)
return r; return r;
} }
} else { } else {
return (Result) {errorObject(NULL_PARSE), NULL}; return (Result) { errorObject(NULL_PARSE), NULL };
} }
} }
@ -376,7 +380,7 @@ Result readSeq(struct Slice* tokens)
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);
sugar("(? fil) => (? 'fil')" // or, sugar("(? fil) => (? 'fil')" // or,
@ -446,36 +450,34 @@ Result 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 (Result) {parseDecimal(s), s}; return (Result) { parseDecimal(s), s };
#ifndef LOW_MEM #ifndef LOW_MEM
} else if (s->text[1] == 'x') { } else if (s->text[1] == 'x') {
return (Result) {parseHex(s), s}; return (Result) { parseHex(s), s };
} else if (s->text[1] == 'b') { } else if (s->text[1] == 'b') {
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;

View File

@ -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",

View File

@ -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);
} }

View File

@ -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)

View File

@ -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

View File

@ -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.*"

View File

@ -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)
{ {