Began `cat` code and added `spent` demo func

This commit is contained in:
= 2020-05-10 07:27:59 +01:00
parent 874420b3d5
commit d83fa29bb4
4 changed files with 78 additions and 1 deletions

View File

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

View File

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

View File

@ -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(">", &gth, &e);
addFunc("<", &lth, &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;
}

View File

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