Began `cat` code and added `spent` demo func
This commit is contained in:
parent
874420b3d5
commit
d83fa29bb4
31
src/object.c
31
src/object.c
|
@ -238,6 +238,8 @@ char* stringObj(char *dest, const Object *obj)
|
||||||
snprintf(dest, RESULT_LENGTH, "%s", obj->number ? "T" : "F");
|
snprintf(dest, RESULT_LENGTH, "%s", obj->number ? "T" : "F");
|
||||||
} else if(t == TYPE_ERROR) {
|
} else if(t == TYPE_ERROR) {
|
||||||
snprintf(dest, RESULT_LENGTH, "E%d", obj->err);
|
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) {
|
} else if(t == TYPE_LIST) {
|
||||||
stringList(dest, obj);
|
stringList(dest, obj);
|
||||||
} else {
|
} else {
|
||||||
|
@ -324,6 +326,12 @@ void cleanObject(Object *target)
|
||||||
free(target->lambda);
|
free(target->lambda);
|
||||||
} else if(t == TYPE_LIST) {
|
} else if(t == TYPE_LIST) {
|
||||||
deleteList(target);
|
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;
|
target->forward = NULL;
|
||||||
}
|
}
|
||||||
|
@ -437,6 +445,29 @@ inline Object lambdaObject()
|
||||||
return o;
|
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)
|
inline Object constructLambda(const Object *params, const Object *body)
|
||||||
{
|
{
|
||||||
if(!params || !body)
|
if(!params || !body)
|
||||||
|
|
|
@ -63,13 +63,14 @@ typedef enum Type {
|
||||||
TYPE_FUNC,
|
TYPE_FUNC,
|
||||||
TYPE_SYMBOL,
|
TYPE_SYMBOL,
|
||||||
TYPE_LAMBDA,
|
TYPE_LAMBDA,
|
||||||
|
TYPE_STRING,
|
||||||
TYPE_ERROR
|
TYPE_ERROR
|
||||||
} Type;
|
} Type;
|
||||||
|
|
||||||
typedef struct Object Object;
|
typedef struct Object Object;
|
||||||
struct Lambda;
|
struct Lambda;
|
||||||
|
|
||||||
struct Environment;
|
struct Environment;
|
||||||
|
struct Slice;
|
||||||
|
|
||||||
struct Object {
|
struct Object {
|
||||||
Type type;
|
Type type;
|
||||||
|
@ -78,6 +79,7 @@ struct Object {
|
||||||
int number;
|
int number;
|
||||||
Object *list;
|
Object *list;
|
||||||
char name[MAX_TOK_LEN];
|
char name[MAX_TOK_LEN];
|
||||||
|
char *string;
|
||||||
Object (*func)(Object, Object, struct Environment *env);
|
Object (*func)(Object, Object, struct Environment *env);
|
||||||
struct Lambda *lambda; // Maybe better as not a pointer?
|
struct Lambda *lambda; // Maybe better as not a pointer?
|
||||||
enum errorCode err;
|
enum errorCode err;
|
||||||
|
@ -118,6 +120,7 @@ Object listObject();
|
||||||
Object startList(const Object start);
|
Object startList(const Object start);
|
||||||
Object lambdaObject();
|
Object lambdaObject();
|
||||||
Object symbolObject();
|
Object symbolObject();
|
||||||
|
Object objFromSlice(const char *string, int len);
|
||||||
Object boolObject(int b);
|
Object boolObject(int b);
|
||||||
Object numberObject(int num);
|
Object numberObject(int num);
|
||||||
Object errorObject(enum errorCode err);
|
Object errorObject(enum errorCode err);
|
||||||
|
|
|
@ -106,6 +106,8 @@ Object parseAtom(struct Slice *s)
|
||||||
} else if (s->text[0] == 'F' && s->length == 1) {
|
} else if (s->text[0] == 'F' && s->length == 1) {
|
||||||
return boolObject(0);
|
return boolObject(0);
|
||||||
|
|
||||||
|
} else if (s->text[0] == '"') {
|
||||||
|
return objFromSlice(s->text, s->length);
|
||||||
} else {
|
} else {
|
||||||
Object o = symbolObject();
|
Object o = symbolObject();
|
||||||
copySlice(o.name, s);
|
copySlice(o.name, s);
|
||||||
|
@ -234,6 +236,7 @@ Object eval(const Object *obj, struct Environment *env)
|
||||||
switch(obj->type) {
|
switch(obj->type) {
|
||||||
case TYPE_NUMBER:
|
case TYPE_NUMBER:
|
||||||
case TYPE_BOOL:
|
case TYPE_BOOL:
|
||||||
|
case TYPE_STRING:
|
||||||
return *obj; // Return as is
|
return *obj; // Return as is
|
||||||
|
|
||||||
case TYPE_SYMBOL:
|
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)
|
Object _basicOp(const Object *obj1, const Object *obj2, const char op)
|
||||||
{
|
{
|
||||||
const int n1 = obj1->number;
|
const int n1 = obj1->number;
|
||||||
|
@ -367,6 +389,8 @@ Object _basicOp(const Object *obj1, const Object *obj2, const char op)
|
||||||
return numberObject(n1 * n2);
|
return numberObject(n1 * n2);
|
||||||
case '/':
|
case '/':
|
||||||
return numberObject(n1 / n2);
|
return numberObject(n1 / n2);
|
||||||
|
case '%':
|
||||||
|
return numberObject(n1 % n2);
|
||||||
|
|
||||||
case '=':
|
case '=':
|
||||||
return boolObject(n1 == n2);
|
return boolObject(n1 == n2);
|
||||||
|
@ -417,6 +441,7 @@ bopf(add, '+');
|
||||||
bopf(sub, '-');
|
bopf(sub, '-');
|
||||||
bopf(mul, '*');
|
bopf(mul, '*');
|
||||||
bopf(dvi, '/');
|
bopf(dvi, '/');
|
||||||
|
bopf(mod, '%');
|
||||||
bopf(equ, '=');
|
bopf(equ, '=');
|
||||||
bopf(gth, '>');
|
bopf(gth, '>');
|
||||||
bopf(lth, '<');
|
bopf(lth, '<');
|
||||||
|
@ -455,13 +480,22 @@ struct Environment defaultEnv() {
|
||||||
addFunc("-", &sub, &e);
|
addFunc("-", &sub, &e);
|
||||||
addFunc("*", &mul, &e);
|
addFunc("*", &mul, &e);
|
||||||
addFunc("/", &dvi, &e);
|
addFunc("/", &dvi, &e);
|
||||||
|
addFunc("%", &mod, &e);
|
||||||
addFunc("=", &equ, &e);
|
addFunc("=", &equ, &e);
|
||||||
addFunc(">", >h, &e);
|
addFunc(">", >h, &e);
|
||||||
addFunc("<", <h, &e);
|
addFunc("<", <h, &e);
|
||||||
addFunc("len", &len, &e);
|
addFunc("len", &len, &e);
|
||||||
|
addFunc("cat", &catObjects, &e);
|
||||||
|
|
||||||
parseEval("(def max (fn (a b) (if (> a b) a b)))", &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 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 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;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,15 @@ struct Slice *nf_tokenize(const char *input)
|
||||||
slice++;
|
slice++;
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
|
} else if(input[i] == '"') {
|
||||||
|
slices[slice].text = &input[i];
|
||||||
|
int l = 1;
|
||||||
|
while(input[++i] != '"') {
|
||||||
|
l++;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
slices[slice].length = l;
|
||||||
|
slice++;
|
||||||
} else {
|
} else {
|
||||||
slices[slice].text = &input[i];
|
slices[slice].text = &input[i];
|
||||||
int l = 1;
|
int l = 1;
|
||||||
|
|
Loading…
Reference in New Issue