M include/expr.h => include/expr.h +2 -0
@@ 13,6 13,7 @@ enum expression_kind {
/* Special forms */
EXPR_LAMBDA,
+ EXPR_PAIR,
EXPR_QUOTE,
EXPR_UNQUOTE,
};
@@ 35,6 36,7 @@ struct expression {
char *symbol;
struct expression *quoted;
+ struct expression *pair[2];
};
};
M src/env.c => src/env.c +51 -0
@@ 303,6 303,53 @@ env_if(struct location loc, struct list_expression *list,
}
static struct expression *
+env_cons(struct location loc, struct list_expression *list,
+ struct binding **bindings)
+{
+ if (!list || !list->next) {
+ error(loc, "Not enough arguments");
+ }
+
+ struct expression *new = mkexpression();
+ new->kind = EXPR_PAIR;
+ new->pair[0] = eval(list->expr, bindings);
+ new->pair[1] = eval(list->next->expr, bindings);
+ return new;
+}
+
+static struct expression *
+env_car(struct location loc, struct list_expression *list,
+ struct binding **bindings)
+{
+ if (!list) {
+ error(loc, "Not enough arguments");
+ }
+
+ struct expression *pair = eval(list->expr, bindings);
+ if (pair->kind != EXPR_PAIR) {
+ error(loc, "car must be used on a pair");
+ }
+
+ return expression_dup(pair->pair[0]);
+}
+
+static struct expression *
+env_cdr(struct location loc, struct list_expression *list,
+ struct binding **bindings)
+{
+ if (!list) {
+ error(loc, "Not enough arguments");
+ }
+
+ struct expression *pair = eval(list->expr, bindings);
+ if (pair->kind != EXPR_PAIR) {
+ error(loc, "cdr must be used on a pair");
+ }
+
+ return expression_dup(pair->pair[1]);
+}
+
+static struct expression *
env_display(struct location loc, struct list_expression *list,
struct binding **bindings)
{
@@ 348,6 395,10 @@ environment[] = {
{ .name = "define", .func = &env_define },
{ .name = "if", .func = &env_if },
+ { .name = "cons", .func = &env_cons },
+ { .name = "car", .func = &env_car },
+ { .name = "cdr", .func = &env_cdr },
+
{ .name = "display", .func = &env_display },
{ .name = "newline", .func = &env_newline },
M src/expr.c => src/expr.c +15 -0
@@ 40,6 40,10 @@ expression_dup(struct expression *expr)
newl = &(*newl)->next;
}
break;
+ case EXPR_PAIR:
+ new->pair[0] = expression_dup(expr->pair[0]);
+ new->pair[1] = expression_dup(expr->pair[1]);
+ break;
case EXPR_STRING:
new->string = xstrdup(expr->string);
break;
@@ 74,6 78,10 @@ expression_free(struct expression *expr)
case EXPR_UNQUOTE:
expression_free(expr->quoted);
break;
+ case EXPR_PAIR:
+ expression_free(expr->pair[0]);
+ expression_free(expr->pair[1]);
+ break;
case EXPR_STRING:
free(expr->string);
break;
@@ 110,6 118,13 @@ expression_print(FILE *out, struct expression *expr)
fputs(",", out);
expression_print(out, expr->quoted);
break;
+ case EXPR_PAIR:
+ fputs("(", out);
+ expression_print(out, expr->pair[0]);
+ fputs(" . ", out);
+ expression_print(out, expr->pair[1]);
+ fputs(")", out);
+ break;
case EXPR_STRING:
fputs("\"", out);
for (size_t i = 0; expr->string[i] != '\0'; i++) {