diff --git a/src/list.c b/src/list.c index 0386657..b834eda 100644 --- a/src/list.c +++ b/src/list.c @@ -43,6 +43,14 @@ LakeList *list_make(void) return list; } +LakeList *list_cons(LakeVal *car, LakeVal *cdr) +{ + LakeList *list = list_make_with_capacity(2); + list->vals[0] = car; + list->vals[1] = cdr; + return list; +} + LakeList *list_make_with_capacity(size_t cap) { LakeList *list = list_alloc(); diff --git a/src/list.h b/src/list.h index e15a066..8c40fd1 100644 --- a/src/list.h +++ b/src/list.h @@ -15,6 +15,7 @@ #include "string.h" LakeList *list_make(void); +LakeList *list_cons(LakeVal *car, LakeVal *cdr); void list_free(LakeList *list); LakeList *list_make_with_capacity(size_t cap); LakeList *list_from_array(size_t n, LakeVal *vals[]); diff --git a/src/primitive.c b/src/primitive.c index 6af7d8f..40d525a 100644 --- a/src/primitive.c +++ b/src/primitive.c @@ -164,6 +164,35 @@ static LakeVal *prim_int_eq(LakeList *args) return VAL(bool_from_int(result)); } +static LakeVal *prim_car(LakeList *args) +{ + LakeList *list = LIST(LIST_VAL(args, 0)); + if (IS(TYPE_LIST, list) && LIST_N(list) > 0) { + return LIST_VAL(list, 0); + } + ERR("not a pair: %s", list_repr(list)); + return NULL; +} + +static LakeVal *prim_cdr(LakeList *args) +{ + LakeList *list = LIST(LIST_VAL(args, 0)); + if (IS(TYPE_LIST, list) && LIST_N(list) > 0) { + LakeList *cdr = list_copy(list); + list_shift(cdr); + return VAL(cdr); + } + ERR("not a pair: %s", list_repr(list)); + return NULL; +} + +static LakeVal *prim_cons(LakeList *args) +{ + LakeVal *car = LIST_VAL(args, 0); + LakeVal *cdr = LIST_VAL(args, 1); + return VAL(list_cons(car, cdr)); +} + Env *primitive_bindings(void) { #define DEFINE(name, fn, arity) env_define(env, sym_intern(name), VAL(prim_make(name, arity, fn))) @@ -177,5 +206,8 @@ Env *primitive_bindings(void) DEFINE("*", prim_mul, ARITY_VARARGS); DEFINE("/", prim_div, ARITY_VARARGS); DEFINE("=", prim_int_eq, ARITY_VARARGS); + DEFINE("car", prim_car, 1); + DEFINE("cdr", prim_cdr, 1); + DEFINE("cons", prim_cons, 2); return env; }