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_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)
|
||||
|
||||
|
|
|
@ -412,6 +412,7 @@ struct Environment defaultEnv()
|
|||
pf(append),
|
||||
pf(prepend),
|
||||
pf(reduce),
|
||||
pf(mapO),
|
||||
pf(at),
|
||||
pf(rest),
|
||||
pf(charAt),
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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(¶ms[0], env);
|
||||
const Object* inputList = ¶ms[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;
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.*"
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
*/
|
||||
|
||||
// Is the char a standalone token?
|
||||
static const char singleTokens[] = "()+-*/='?";
|
||||
static const char singleTokens[] = "()+-*/='?.";
|
||||
|
||||
int isSingle(const char c)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue