Browse Source

1st attempt to implement head & tail functions

T. Meissner 7 months 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) {
170 170
 
171 171
     /* Fill this list with any valid expression
172 172
        contained within */
173
-    for (size_t i = 0; i < t->children_num; i++) {
173
+    for (size_t i = 0; i < (size_t) t->children_num; i++) {
174 174
         if (strcmp(t->children[i]->contents, "(") == 0) {
175 175
             continue;
176 176
         }
@@ -415,6 +415,66 @@ lval* builtin_op(lval* a, char* op) {
415 415
 }
416 416
 
417 417
 
418
+lval* builtin_head(lval* a) {
419
+
420
+    /* Check error conditions */
421
+    if (a->count != 1) {
422
+        lval_del(a);
423
+        return lval_err("Function 'head' passed too many arguments");
424
+    }
425
+
426
+    if (a->cell[0]->type != LVAL_QEXPR) {
427
+        lval_del(a);
428
+        return lval_err("Function 'head' passed incorrect types!");
429
+    }
430
+
431
+    if (a->cell[0]->count == 0) {
432
+        lval_del(a);
433
+        return lval_err("Function 'head' passed empty {}!");
434
+    }
435
+
436
+    /* Otherwise take first argument */
437
+    lval* v = lval_take(a, 0);
438
+
439
+    /* Delete all elements that are not head and return */
440
+    while (v-> count > 1) {
441
+        lval_del(lval_pop(v, 1));
442
+    }
443
+
444
+    return v;
445
+
446
+}
447
+
448
+
449
+lval* builtin_tail(lval* a) {
450
+
451
+    /* Check error conditions */
452
+    if (a->count != 1) {
453
+        lval_del(a);
454
+        return lval_err("Function 'tail' passed too many arguments");
455
+    }
456
+
457
+    if (a->cell[0]->type != LVAL_QEXPR) {
458
+        lval_del(a);
459
+        return lval_err("Function 'tail' passed incorrect types!");
460
+    }
461
+
462
+    if (a->cell[0]->count == 0) {
463
+        lval_del(a);
464
+        return lval_err("Function 'tail' passed empty {}!");
465
+    }
466
+
467
+    /* Otherwise take first argument */
468
+    lval* v = lval_take(a, 0);
469
+
470
+    /* Delete first element and return */
471
+    lval_del(lval_pop(v, 0));
472
+
473
+    return v;
474
+
475
+}
476
+
477
+
418 478
 long min(long x, long y) {
419 479
     if (x <= y) {
420 480
         return x;
@@ -433,7 +493,7 @@ long max(long x, long y) {
433 493
 }
434 494
 
435 495
 
436
-int main(int argc, char const *argv[]) {
496
+int main() {
437 497
 
438 498
     /* Create some parsers */
439 499
     mpc_parser_t* Number = mpc_new("number");
@@ -477,7 +537,7 @@ int main(int argc, char const *argv[]) {
477 537
     }
478 538
 
479 539
     /* Undefine and delete our parsers */
480
-    mpc_cleanup(5, Number, Symbol, Sexpr, Qexpr, Expr, Lispy);
540
+    mpc_cleanup(6, Number, Symbol, Sexpr, Qexpr, Expr, Lispy);
481 541
 
482 542
     return 0;
483 543
 }

+ 21
- 12
chapter_10/lispy.h View File

@@ -3,22 +3,27 @@ static char* lispy_version = "Lispy version 0.0.0.0.6";
3 3
 
4 4
 /* Parser language defintion */
5 5
 static char* parser =
6
-"                                                        \
7
-    number   : /-?[0-9]+([.][0-9]*|[0-9]*)/ ;            \
8
-    symbol : '+' | '-' | '*' | '/' | '%' | '^' |         \
9
-    \"min\" | \"max\" ;                                  \
10
-    sexpr    : '(' <expr>* ')' ;                         \
11
-    qexpr    : '{' <expr>* '}' ;                         \
12
-    expr     : <number> | <symbol> | <sexpr> | <qexpr>;  \
13
-    lispy    : /^/ <expr>* /$/ ;                         \
6
+"                                                         \
7
+    number   : /-?[0-9]+([.][0-9]*|[0-9]*)/ ;             \
8
+    symbol : \"list\" | \"head\" | \"tail\" | \"join\" |  \
9
+             \"eval\" | '+' | '-' | '*' | '/' | '%' |     \
10
+             '^' | \"min\" | \"max\" ;                    \
11
+    sexpr    : '(' <expr>* ')' ;                          \
12
+    qexpr    : '{' <expr>* '}' ;                          \
13
+    expr     : <number> | <symbol> | <sexpr> | <qexpr>;   \
14
+    lispy    : /^/ <expr>* /$/ ;                          \
14 15
 ";
15 16
 
16 17
 
17 18
 /* Declare new lval struct */
18 19
 typedef struct lval {
19 20
     int type;
20
-    long num;
21
-    double dec;
21
+    /* only one of the two number/decimal is valid in a
22
+       lval instance, so we can use an anonymous union */
23
+    union {
24
+        long num;
25
+        double dec;
26
+    };
22 27
     /* Error & symbol types have some string data */
23 28
     char* err;
24 29
     char* sym;
@@ -29,7 +34,8 @@ typedef struct lval {
29 34
 
30 35
 
31 36
 /* Create enumeration of possible lval types */
32
-enum {LVAL_NUM, LVAL_DEC, LVAL_SYM, LVAL_SEXPR, LVAL_QEXPR, LVAL_ERR};
37
+enum lval_types {LVAL_NUM, LVAL_DEC, LVAL_SYM, LVAL_SEXPR,
38
+                 LVAL_QEXPR, LVAL_ERR};
33 39
 
34 40
 /* lval constructor functions */
35 41
 lval* lval_num(long x);
@@ -52,11 +58,14 @@ lval* lval_read(mpc_ast_t* t);
52 58
 lval* lval_eval_sexpr(lval* v);
53 59
 lval* lval_eval(lval* v);
54 60
 
61
+/* lval print functions */
55 62
 void lval_expr_print(lval* v, char open, char close);
56 63
 void lval_print(lval* v);
57 64
 void lval_println(lval* v);
58 65
 
66
+/* language built-in operators and functions */
59 67
 long min(long x, long y);
60 68
 long max(long x, long y);
61
-
62 69
 lval* builtin_op(lval* a, char* op);
70
+lval* builtin_head(lval* a);
71
+lval* builtin_tail(lval* a);