diff --git a/src/object.c b/src/object.c index b26e1dc..2a3ab20 100644 --- a/src/object.c +++ b/src/object.c @@ -238,6 +238,8 @@ char* stringObj(char *dest, const Object *obj) snprintf(dest, RESULT_LENGTH, "%s", obj->number ? "T" : "F"); } else if(t == TYPE_ERROR) { snprintf(dest, RESULT_LENGTH, "E%d", obj->err); + } else if(t == TYPE_STRING) { + snprintf(dest, RESULT_LENGTH, "%s", obj->string); } else if(t == TYPE_LIST) { stringList(dest, obj); } else { @@ -324,6 +326,12 @@ void cleanObject(Object *target) free(target->lambda); } else if(t == TYPE_LIST) { deleteList(target); + } else if(t == TYPE_STRING) { + // TODO Why does this break? + // Probably multiple objects referencing the same string + + // free(target->string); + // target->string = NULL; } target->forward = NULL; } @@ -437,6 +445,29 @@ inline Object lambdaObject() return o; } +// Skips first char! Assumed to be '"' +inline Object objFromSlice(const char *string, int len) +{ + Object o = newObject(TYPE_STRING); + o.string = calloc(sizeof(char), len); + for(int i = 0; i < len - 1; i++) { + o.string[i] = string[i + 1]; + } + o.string[len - 1] = '\0'; + return o; +} + +// inline Object objFromString(const char *string) +// { +// Object o = newObject(TYPE_STRING); +// o.string = calloc(strlen(string) + 1); +// for(int i = 0; i < len - 1; i++) { +// o.string[i] = string[i]; +// } +// o.string[len - 1] = '\0'; +// return o; +// } + inline Object constructLambda(const Object *params, const Object *body) { if(!params || !body) diff --git a/src/object.h b/src/object.h index cf2161e..99477fc 100644 --- a/src/object.h +++ b/src/object.h @@ -63,13 +63,14 @@ typedef enum Type { TYPE_FUNC, TYPE_SYMBOL, TYPE_LAMBDA, + TYPE_STRING, TYPE_ERROR } Type; typedef struct Object Object; struct Lambda; - struct Environment; +struct Slice; struct Object { Type type; @@ -78,6 +79,7 @@ struct Object { int number; Object *list; char name[MAX_TOK_LEN]; + char *string; Object (*func)(Object, Object, struct Environment *env); struct Lambda *lambda; // Maybe better as not a pointer? enum errorCode err; @@ -118,6 +120,7 @@ Object listObject(); Object startList(const Object start); Object lambdaObject(); Object symbolObject(); +Object objFromSlice(const char *string, int len); Object boolObject(int b); Object numberObject(int num); Object errorObject(enum errorCode err); diff --git a/src/pebblisp.c b/src/pebblisp.c index 7107b9f..fdcdef2 100644 --- a/src/pebblisp.c +++ b/src/pebblisp.c @@ -106,6 +106,8 @@ Object parseAtom(struct Slice *s) } else if (s->text[0] == 'F' && s->length == 1) { return boolObject(0); + } else if (s->text[0] == '"') { + return objFromSlice(s->text, s->length); } else { Object o = symbolObject(); copySlice(o.name, s); @@ -234,6 +236,7 @@ Object eval(const Object *obj, struct Environment *env) switch(obj->type) { case TYPE_NUMBER: case TYPE_BOOL: + case TYPE_STRING: return *obj; // Return as is case TYPE_SYMBOL: @@ -353,6 +356,25 @@ void printEnv(struct Environment *env) } } +Object catObjects(const Object obj1, const Object obj2, struct Environment *env) +{ + const Object evalObj1 = eval(&obj1, env); + const Object evalObj2 = eval(&obj2, env); + + char str1[100] = ""; + char str2[100] = ""; + stringObj(str1, &evalObj1); + stringObj(str2, &evalObj2); + int length = strlen(str1) + strlen(str2) + 1; + + Object o = newObject(TYPE_STRING); + o.string = calloc(sizeof(char), length); + strcat(o.string, str1); + strcat(o.string, str2); + + return o; +} + Object _basicOp(const Object *obj1, const Object *obj2, const char op) { const int n1 = obj1->number; @@ -367,6 +389,8 @@ Object _basicOp(const Object *obj1, const Object *obj2, const char op) return numberObject(n1 * n2); case '/': return numberObject(n1 / n2); + case '%': + return numberObject(n1 % n2); case '=': return boolObject(n1 == n2); @@ -417,6 +441,7 @@ bopf(add, '+'); bopf(sub, '-'); bopf(mul, '*'); bopf(dvi, '/'); +bopf(mod, '%'); bopf(equ, '='); bopf(gth, '>'); bopf(lth, '<'); @@ -455,13 +480,22 @@ struct Environment defaultEnv() { addFunc("-", &sub, &e); addFunc("*", &mul, &e); addFunc("/", &dvi, &e); + addFunc("%", &mod, &e); addFunc("=", &equ, &e); addFunc(">", >h, &e); addFunc("<", <h, &e); addFunc("len", &len, &e); + addFunc("cat", &catObjects, &e); + parseEval("(def max (fn (a b) (if (> a b) a b)))", &e); parseEval("(def min (fn (a b) (if (< a b) a b)))", &e); parseEval("(def ad (fn (a) (if (> a 10) a (ad (* 10 a) ))))", &e); + parseEval("(def spent (fn (a) \ + (cat \"Tip: $\" (/ a 5) \".\" \ + (/ (* 100 (% a 5)) 5) \ + ) \ + ))", + &e); return e; } diff --git a/src/tokens.c b/src/tokens.c index c8eb88d..bef850d 100644 --- a/src/tokens.c +++ b/src/tokens.c @@ -75,6 +75,15 @@ struct Slice *nf_tokenize(const char *input) slice++; i++; + } else if(input[i] == '"') { + slices[slice].text = &input[i]; + int l = 1; + while(input[++i] != '"') { + l++; + } + i++; + slices[slice].length = l; + slice++; } else { slices[slice].text = &input[i]; int l = 1;