diff --git a/lib/am.c b/lib/am.c index 6c98bd3..9994321 100644 --- a/lib/am.c +++ b/lib/am.c @@ -36,3 +36,20 @@ void am_append(am_t *am, am_reg_t list_reg, am_reg_t item_reg) list->pair.car = am->regs[item_reg]; list->pair.cdr = expr_empty_list(am); } + +void am_car(am_t *am, am_reg_t dest, am_reg_t src) +{ + assert(!am->regs[src]->is_atom); + am->regs[dest] = am->regs[src]->pair.car; +} + +void am_cdr(am_t *am, am_reg_t dest, am_reg_t src) +{ + assert(!am->regs[src]->is_atom); + am->regs[dest] = am->regs[src]->pair.cdr; +} + +void am_assign(am_t *am, am_reg_t dest, am_reg_t src) +{ + am->regs[dest] = am->regs[src]; +} diff --git a/lib/eval.c b/lib/eval.c index 6e47e2e..74a0c99 100644 --- a/lib/eval.c +++ b/lib/eval.c @@ -10,7 +10,7 @@ static void eval_atom(am_t *am) case ATOM_TYPE_EMPTY_LIST: case ATOM_TYPE_INTEGER: case ATOM_TYPE_PRIM_PROC: - AM_VAL(am) = AM_EXPR(am); + am_assign(am, VAL, EXPR); break; case ATOM_TYPE_SYMBOL: env_fetch(am); @@ -21,23 +21,24 @@ static void eval_atom(am_t *am) static void eval_list(am_t *am) { AM_ARGL(am) = expr_empty_list(am); - AM_UNEV(am) = AM_EXPR(am)->pair.cdr; - AM_EXPR(am) = AM_EXPR(am)->pair.car; + am_cdr(am, UNEV, EXPR); + am_car(am, EXPR, EXPR); while (!AM_UNEV(am)->is_atom) { - am_push(am, EXPR); - AM_EXPR(am) = AM_UNEV(am)->pair.cdr; am_push(am, EXPR); am_push(am, ARGL); - AM_EXPR(am) = AM_UNEV(am)->pair.car; + am_car(am, EXPR, UNEV); + am_cdr(am, UNEV, UNEV); + am_push(am, UNEV); + eval(am); - am_pop(am, ARGL); - am_append(am, ARGL, VAL); - am_pop(am, UNEV); + am_pop(am, ARGL); am_pop(am, EXPR); + + am_append(am, ARGL, VAL); } assert(AM_EXPR(am)->is_atom); diff --git a/lib/include/am.h b/lib/include/am.h index 4f3072d..3c5867e 100644 --- a/lib/include/am.h +++ b/lib/include/am.h @@ -32,5 +32,8 @@ void am_init(am_t *am); void am_push(am_t *am, am_reg_t reg); void am_pop(am_t *am, am_reg_t reg); void am_append(am_t *am, am_reg_t list_reg, am_reg_t item_reg); +void am_car(am_t *am, am_reg_t dest, am_reg_t src); +void am_cdr(am_t *am, am_reg_t dest, am_reg_t src); +void am_assign(am_t *am, am_reg_t dest, am_reg_t src); #endif diff --git a/tests/am_tests.c b/tests/am_tests.c index d3e46df..129324f 100644 --- a/tests/am_tests.c +++ b/tests/am_tests.c @@ -81,6 +81,41 @@ static void test_append_unev_2_to_expr_list_1(void) TEST_ASSERT_EQUAL(2, CADR(am.regs[EXPR])->atom.integer); } +static void test_car_of_expr_pair_1_2(void) +{ + am.regs[EXPR] + = expr_pair(&am, expr_integer(&am, 1), expr_integer(&am, 2)); + am_car(&am, EXPR, EXPR); + + TEST_ASSERT_NOT_NULL(am.regs[EXPR]); + TEST_ASSERT_TRUE(am.regs[EXPR]->is_atom); + TEST_ASSERT_EQUAL(ATOM_TYPE_INTEGER, am.regs[EXPR]->atom.type); + TEST_ASSERT_EQUAL(1, am.regs[EXPR]->atom.integer); +} + +static void test_cdr_of_expr_pair_1_2(void) +{ + am.regs[EXPR] + = expr_pair(&am, expr_integer(&am, 1), expr_integer(&am, 2)); + am_cdr(&am, EXPR, EXPR); + + TEST_ASSERT_NOT_NULL(am.regs[EXPR]); + TEST_ASSERT_TRUE(am.regs[EXPR]->is_atom); + TEST_ASSERT_EQUAL(ATOM_TYPE_INTEGER, am.regs[EXPR]->atom.type); + TEST_ASSERT_EQUAL(2, am.regs[EXPR]->atom.integer); +} + +static void test_assign_expr_to_val(void) +{ + am.regs[EXPR] = expr_integer(&am, 42); + am_assign(&am, VAL, EXPR); + + TEST_ASSERT_NOT_NULL(am.regs[EXPR]); + TEST_ASSERT_TRUE(am.regs[EXPR]->is_atom); + TEST_ASSERT_EQUAL(ATOM_TYPE_INTEGER, am.regs[EXPR]->atom.type); + TEST_ASSERT_EQUAL(42, am.regs[EXPR]->atom.integer); +} + int main(void) { UNITY_BEGIN(); @@ -88,5 +123,8 @@ int main(void) RUN_TEST(test_argl_value_restored_after_push_modify_pop); RUN_TEST(test_append_val_42_to_empty_argl); RUN_TEST(test_append_unev_2_to_expr_list_1); + RUN_TEST(test_car_of_expr_pair_1_2); + RUN_TEST(test_cdr_of_expr_pair_1_2); + RUN_TEST(test_assign_expr_to_val); return UNITY_END(); }