diff --git a/chapter_10/lispy.c b/chapter_10/lispy.c index aa6cbfc..1246401 100644 --- a/chapter_10/lispy.c +++ b/chapter_10/lispy.c @@ -170,7 +170,7 @@ lval* lval_read(mpc_ast_t* t) { /* Fill this list with any valid expression contained within */ - for (size_t i = 0; i < t->children_num; i++) { + for (size_t i = 0; i < (size_t) t->children_num; i++) { if (strcmp(t->children[i]->contents, "(") == 0) { continue; } @@ -415,6 +415,66 @@ lval* builtin_op(lval* a, char* op) { } +lval* builtin_head(lval* a) { + + /* Check error conditions */ + if (a->count != 1) { + lval_del(a); + return lval_err("Function 'head' passed too many arguments"); + } + + if (a->cell[0]->type != LVAL_QEXPR) { + lval_del(a); + return lval_err("Function 'head' passed incorrect types!"); + } + + if (a->cell[0]->count == 0) { + lval_del(a); + return lval_err("Function 'head' passed empty {}!"); + } + + /* Otherwise take first argument */ + lval* v = lval_take(a, 0); + + /* Delete all elements that are not head and return */ + while (v-> count > 1) { + lval_del(lval_pop(v, 1)); + } + + return v; + +} + + +lval* builtin_tail(lval* a) { + + /* Check error conditions */ + if (a->count != 1) { + lval_del(a); + return lval_err("Function 'tail' passed too many arguments"); + } + + if (a->cell[0]->type != LVAL_QEXPR) { + lval_del(a); + return lval_err("Function 'tail' passed incorrect types!"); + } + + if (a->cell[0]->count == 0) { + lval_del(a); + return lval_err("Function 'tail' passed empty {}!"); + } + + /* Otherwise take first argument */ + lval* v = lval_take(a, 0); + + /* Delete first element and return */ + lval_del(lval_pop(v, 0)); + + return v; + +} + + long min(long x, long y) { if (x <= y) { return x; @@ -433,7 +493,7 @@ long max(long x, long y) { } -int main(int argc, char const *argv[]) { +int main() { /* Create some parsers */ mpc_parser_t* Number = mpc_new("number"); @@ -477,7 +537,7 @@ int main(int argc, char const *argv[]) { } /* Undefine and delete our parsers */ - mpc_cleanup(5, Number, Symbol, Sexpr, Qexpr, Expr, Lispy); + mpc_cleanup(6, Number, Symbol, Sexpr, Qexpr, Expr, Lispy); return 0; } diff --git a/chapter_10/lispy.h b/chapter_10/lispy.h index 82a9778..bba67f5 100644 --- a/chapter_10/lispy.h +++ b/chapter_10/lispy.h @@ -3,22 +3,27 @@ static char* lispy_version = "Lispy version 0.0.0.0.6"; /* Parser language defintion */ static char* parser = -" \ - number : /-?[0-9]+([.][0-9]*|[0-9]*)/ ; \ - symbol : '+' | '-' | '*' | '/' | '%' | '^' | \ - \"min\" | \"max\" ; \ - sexpr : '(' * ')' ; \ - qexpr : '{' * '}' ; \ - expr : | | | ; \ - lispy : /^/ * /$/ ; \ +" \ + number : /-?[0-9]+([.][0-9]*|[0-9]*)/ ; \ + symbol : \"list\" | \"head\" | \"tail\" | \"join\" | \ + \"eval\" | '+' | '-' | '*' | '/' | '%' | \ + '^' | \"min\" | \"max\" ; \ + sexpr : '(' * ')' ; \ + qexpr : '{' * '}' ; \ + expr : | | | ; \ + lispy : /^/ * /$/ ; \ "; /* Declare new lval struct */ typedef struct lval { int type; - long num; - double dec; + /* only one of the two number/decimal is valid in a + lval instance, so we can use an anonymous union */ + union { + long num; + double dec; + }; /* Error & symbol types have some string data */ char* err; char* sym; @@ -29,7 +34,8 @@ typedef struct lval { /* Create enumeration of possible lval types */ -enum {LVAL_NUM, LVAL_DEC, LVAL_SYM, LVAL_SEXPR, LVAL_QEXPR, LVAL_ERR}; +enum lval_types {LVAL_NUM, LVAL_DEC, LVAL_SYM, LVAL_SEXPR, + LVAL_QEXPR, LVAL_ERR}; /* lval constructor functions */ lval* lval_num(long x); @@ -52,11 +58,14 @@ lval* lval_read(mpc_ast_t* t); lval* lval_eval_sexpr(lval* v); lval* lval_eval(lval* v); +/* lval print functions */ void lval_expr_print(lval* v, char open, char close); void lval_print(lval* v); void lval_println(lval* v); +/* language built-in operators and functions */ long min(long x, long y); long max(long x, long y); - lval* builtin_op(lval* a, char* op); +lval* builtin_head(lval* a); +lval* builtin_tail(lval* a);