Browse Source

1st attempt to implement head & tail functions

master
T. Meissner 5 years ago
parent
commit
0b21a97e7f
2 changed files with 84 additions and 15 deletions
  1. +63
    -3
      chapter_10/lispy.c
  2. +21
    -12
      chapter_10/lispy.h

+ 63
- 3
chapter_10/lispy.c View File

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

+ 21
- 12
chapter_10/lispy.h View File

@ -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 : '(' <expr>* ')' ; \
qexpr : '{' <expr>* '}' ; \
expr : <number> | <symbol> | <sexpr> | <qexpr>; \
lispy : /^/ <expr>* /$/ ; \
" \
number : /-?[0-9]+([.][0-9]*|[0-9]*)/ ; \
symbol : \"list\" | \"head\" | \"tail\" | \"join\" | \
\"eval\" | '+' | '-' | '*' | '/' | '%' | \
'^' | \"min\" | \"max\" ; \
sexpr : '(' <expr>* ')' ; \
qexpr : '{' <expr>* '}' ; \
expr : <number> | <symbol> | <sexpr> | <qexpr>; \
lispy : /^/ <expr>* /$/ ; \
";
/* 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);

Loading…
Cancel
Save