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_COM ?= gcc -O0 $(GCC_ARGS)
all:
$(GCC_COM) $(file_libs) && echo && ./tests.sh
release:
gcc -O3 $(GCC_ARGS) $(file_libs) && strip ./$(exe) && echo && ./tests.sh
notest:
$(GCC_COM) $(file_libs)
all: notest
echo && ./tests.sh
local:
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(prepend),
pf(reduce),
pf(mapO),
pf(at),
pf(rest),
pf(charAt),

View File

@ -15,7 +15,7 @@
(def reload (fn () (loadfile (cat (env "HOME") "/.pebblisp.pbl"))))
(def hour (fn (ti) (
(def h (% ti's hour 12))
(def h (% ti.hour 12))
(if (= 0 h) 12 h)
)))
@ -23,7 +23,7 @@
(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 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.
/// 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);
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 withLen(int len, enum Type type);
Object withLen(size_t len, enum Type type);
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? */
if (getPebbleType(window) == WINDOW) {
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)
{
if (getPebbleType(window) == WINDOW) {
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)
@ -77,9 +77,9 @@ Object updateTextLayer(Object textLayer, Object text, struct Environment* env)
struct PebbleObject* po = accessPebbleObject(textLayer);
stringObj(po->textLayer->text, &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)
@ -130,7 +130,7 @@ Object subscribe(Object function, Object time, struct Environment* env)
6 ? YEAR_UNIT
: MINUTE_UNIT;
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.
*
* Not a typical pl function because I don't feel like adding more syntactic sugar right now.
*
* (struct point (x y))
*/
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.names = malloc(sizeof(char*) * def.fieldCount);
{
int i = 0;
FOR_POINTER_IN_LIST(fields) {
def.names[i] = malloc(sizeof(char) * (strlen(POINTER->string) + 1));
strcpy(def.names[i], POINTER->string);
i++;
}
}
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 condition = eval(argForms, env);
@ -89,19 +92,22 @@ Object evalIfArgs(const Object* argForms, struct Environment* env)
return result;
}
/**
* Not a typical pl function because it relies almost exclusively on symbols
*/
Object evalLambdaArgs(const Object* argForms, struct Environment* 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);
}
Object lambda = eval(argForms, env);
const Object* inputList = argForms->forward;
Object lambda = eval(&params[0], env);
const Object* inputList = &params[1];
if (lambda.type != TYPE_LAMBDA) {
return errorObject(BAD_TYPE);
@ -114,8 +120,8 @@ Object evalMapArgs(const Object* argForms, struct Environment* env)
// since lambda evaluation looks for a list
Object tempInput = cloneObject(*POINTER);
Object* params = &lambda.lambda->params;
struct Environment newEnv = envForLambda(params, &tempInput, listLength(params), env);
Object* lambdaParams = &lambda.lambda->params;
struct Environment newEnv = envForLambda(lambdaParams, &tempInput, listLength(lambdaParams), env);
// Add the lambda evaluation to the list
Object lambda_output = eval(&lambda.lambda->body, &newEnv);
@ -137,8 +143,6 @@ Object evalBuiltIns(const Object* first, const Object* rest,
return evalIfArgs(rest, env);
} else if (strcmp(first->string, "fn") == 0) {
return evalLambdaArgs(rest, env);
} else if (strcmp(first->string, "map") == 0) {
return evalMapArgs(rest, env);
} else if (strcmp(first->string, "struct") == 0) {
return evalStructArgs(rest, rest->forward, env);
}
@ -358,7 +362,7 @@ Result parse(struct Slice* slices)
return r;
}
} 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* rest = next->text ? &next[1] : NULL;
if (next->text[0] == ')') {
return (Result) {res, rest};
return (Result) { res, rest };
}
Result r = parse(tokens);
sugar("(? fil) => (? 'fil')" // or,
@ -446,36 +450,34 @@ Result parseAtom(struct Slice* s)
const char c = s->text[0];
if (isDigit(c)) {
if (c != '0' || s->length == 1) {
return (Result) {parseDecimal(s), s};
return (Result) { parseDecimal(s), s };
#ifndef LOW_MEM
} else if (s->text[1] == 'x') {
return (Result) {parseHex(s), s};
return (Result) { parseHex(s), s };
} else if (s->text[1] == 'b') {
return (Result) {parseBin(s), s};
return (Result) { parseBin(s), s };
#endif
} 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')) {
return (Result) {boolObject(1), s};
} else if (s->length == 1 && (c == 'F' || c == 'f')) {
return (Result) {boolObject(0), s};
} else if (s->length == 1 && c == 'T') {
return (Result) { trueObject(), s };
} else if (s->length == 1 && c == 'F') {
return (Result) { falseObject(), s };
} else if (c == '"'/* || c == '\''*/) {
return (Result) {objFromSlice(s->text, s->length), s};
} else {
if (s->text[s->length] == '\'' && s->text[s->length + 1] == 's') {
return (Result) { objFromSlice(s->text, s->length), s };
} else if (s->text[s->length] == '.') {
Object possessiveFunc = newObject(TYPE_FUNC);
possessiveFunc.func = &possessive;
Object list = startList(possessiveFunc);
Object possesser = symFromSlice(s->text, s->length);
nf_addToList(&list, possesser);
struct Slice* next = s + 3;
struct Slice* next = s + 2;
Object possessed = objFromSlice(&next->text[-1], next->length + 1);
nf_addToList(&list, possessed);
return (Result) {list, next};
}
return (Result) {symFromSlice(s->text, s->length), s};
return (Result) { list, next };
}
return (Result) { symFromSlice(s->text, s->length), s };
}
struct Slice* lastOpen = NULL;

View File

@ -28,6 +28,10 @@ fnn(_name, _docs, __VA_ARGS__)
static const char * const _name ## Symbol = _symbol; \
fnn(_name, _docs, __VA_ARGS__)
#define trueObject() boolObject(1)
#define falseObject() boolObject(0)
struct Slice {
const char* text;
unsigned char length;
@ -68,6 +72,11 @@ int readFile(const char* filename, struct Environment* env);
#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",
"Define a variable in the current scope.",
"(def x 10) x", "10",

View File

@ -44,7 +44,7 @@ Object doVibe(Object patternList, Object o2, struct Environment* env)
}
vibes_enqueue_custom_pattern(
(VibePattern) {.durations = pattern, .num_segments = length});
return boolObject(1);
return trueObject();
} else {
return errorObject(NOT_A_LIST);
}

View File

@ -169,7 +169,7 @@ Object isNum(Object* params, int length, struct Environment* env)
checkTypes(isNum)
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)
@ -177,7 +177,7 @@ Object isList(Object* params, int length, struct Environment* env)
checkTypes(isList)
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)
@ -185,7 +185,7 @@ Object isString(Object* params, int length, struct Environment* env)
checkTypes(isString)
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)
@ -201,7 +201,7 @@ Object isErr(Object* params, int length, struct Environment* env)
checkTypes(isErr)
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)

View File

@ -194,7 +194,7 @@ fn(possessive, "poss",
"Get the value of a struct's field",
"(struct Post (title body))\n "
"(def p (Post \"TI\" \"BO\"))\n "
"p's title", "TI"
"p.title", "TI"
);
#ifdef STANDALONE

View File

@ -205,7 +205,7 @@ check "Building a struct"\
'(struct Post (title body)) (Post "A title" "The Body")'\
'{ title: "A title", body: "The Body" }'
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 "HigherOrder"
@ -217,7 +217,7 @@ check "FuncReturningAFunc" "(def plusser (fn (outer) (fn (inner) (+ outer inner)
title "ShouldError"
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 "BadHex" "(0x0zf)" regex "BAD_NUMBER.*"
check "BadBinary" "(0b01120)" regex "BAD_NUMBER.*"

View File

@ -14,7 +14,7 @@
*/
// Is the char a standalone token?
static const char singleTokens[] = "()+-*/='?";
static const char singleTokens[] = "()+-*/='?.";
int isSingle(const char c)
{