diff --git a/lval/expressions.c b/lval/expressions.c index 9ab6c8c..ab0c205 100644 --- a/lval/expressions.c +++ b/lval/expressions.c @@ -6,7 +6,8 @@ #include "operations.h" #include "error.h" -// Think about where to put this declaration later +// Think about where to put these declarations later +lval* builtin(lval* a, char* func); lval* builtin_op(lval* v, char* op); lval* lval_sexpr(void) { @@ -77,10 +78,68 @@ lval* lval_eval_sexpr(lval* v) { return lval_err("S-expression does not start with symbol"); } - lval* result = builtin_op(v, f->sym); + lval* result = builtin(v, f->sym); lval_del(f); return result; } +lval* builtin_head(lval* a) { + LASSERT(a, a->count == 1, "Function 'head' passed too many arguments") + LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'head' passed incorrect type") + LASSERT(a, a->cell[0]->count != 0, "Function 'head' passed {}") + lval* v = lval_take(a, 0); + while (v->count > 1) { lval_del(lval_pop(v, 1)); } + return v; +} + +lval* builtin_tail(lval* a) { + LASSERT(a, a->count == 1, "Function 'tail' passed too many arguments") + LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'tail' passed incorrect type") + LASSERT(a, a->cell[0]->count != 0, "Function 'tail' passed {}") + + lval* v = lval_take(a, 0); + lval_del(lval_pop(v, 0)); + return v; +} + +lval* builtin_list(lval* a) { + a->type = LVAL_QEXPR; + return a; +} + +lval* builtin_eval(lval* a) { + LASSERT(a, a->count == 1, "Function 'eval' passed too many arguments") + LASSERT(a, a->cell[0]->type == LVAL_QEXPR, "Function 'eval' passed incorrect type") + + lval* x = lval_take(a, 0); + x->type = LVAL_SEXPR; + return lval_eval(x); +} + +lval* lval_join(lval* x, lval* y) { + // For each cell in 'y' add it to 'x' + while (y->count) { + x = lval_add(x, lval_pop(y, 0)); + } + + // Delete the empty y and return x + lval_del(y); + return x; +} + +lval* builtin_join(lval* a) { + for (int i = 0 ; i < a->count; i++) { + LASSERT(a, a->cell[i]->type == LVAL_QEXPR, "Function 'join' passed incorrect type") + } + + lval* x = lval_pop(a, 0); + + while (a->count) { + x = lval_join(x, lval_pop(a, 0)); + } + + lval_del(a); + return x; +} diff --git a/lval/expressions.h b/lval/expressions.h index a813281..c1482ca 100644 --- a/lval/expressions.h +++ b/lval/expressions.h @@ -22,5 +22,20 @@ lval* lval_take(lval* v, int i); // Adds the ability to evalutate each expression in the group lval* lval_eval_sexpr(lval* v); +/* + QEXPR Operations + Head: Takes a Q-Expression and returns a Q-Expression with only of the first element + Tail: Takes a Q-Expression and returns a Q-Expression with the first element removed + List: Takes one or more arguments and returns a new Q-Expression containing the arguments + Eval: Takes a Q-Expression and evaluates it as if it were a S-Expression + Join: join Takes one or more Q-Expressions and returns a Q-Expression of them conjoined together +*/ +lval* builtin_head(lval* a); +lval* builtin_tail(lval* a); +lval* builtin_list(lval* a); +lval* builtin_eval(lval* a); +lval* lval_join(lval* x, lval* y); +lval* builtin_join(lval* a); + #endif diff --git a/prompt.c b/prompt.c index 0107d18..f629658 100644 --- a/prompt.c +++ b/prompt.c @@ -55,7 +55,7 @@ int main (int argc, char** argv) { "double : '.' ; " "symbol : '+' | '-' | '*' | '/' | '%' \ | '^' | \"min\" | \"max\" \ - | \"list\" | \"head\" | \"tail\" | \"join\" | \"eval\" " + | \"list\" | \"head\" | \"tail\" | \"join\" | \"eval\";" "sexpr : '(' * ')'; " "qexpr : '{' * '}'; " @@ -159,3 +159,17 @@ lval* builtin_op(lval* a, char* op) { lval_del(a); return x; } + +lval* builtin(lval* a, char* func) { + if (strcmp("list", func) == 0) { return builtin_list(a); } + if (strcmp("head", func) == 0) { return builtin_head(a); } + if (strcmp("tail", func) == 0) { return builtin_tail(a); } + if (strcmp("join", func) == 0) { return builtin_join(a); } + if (strcmp("eval", func) == 0) { return builtin_eval(a); } + if (strstr("+-/*^%", func)) { return builtin_op(a, func); } + if (strcmp("min", func) == 0) { return builtin_op(a, func); } + if (strcmp("max", func) == 0) { return builtin_op(a, func); } + + lval_del(a); + return lval_err("Unknown Function!"); +} \ No newline at end of file