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");
|
||||
} 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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue