Add 'list' and 'print' builtins
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
LISP_FUNC_1(ucl_builtin_type, state, arg) {
|
||||
switch (arg->type) {
|
||||
@@ -21,6 +22,8 @@ LISP_FUNC_1(ucl_builtin_type, state, arg) {
|
||||
return ucl_symbol_create("string");
|
||||
case UCL_TYPE_ERROR:
|
||||
return ucl_symbol_create("error");
|
||||
case UCL_TYPE_BUILTIN:
|
||||
return ucl_symbol_create("builtin");
|
||||
case UCL_TYPE_COUNT:
|
||||
assert(0);
|
||||
return NULL;
|
||||
@@ -138,7 +141,9 @@ LISP_FUNC_2(ucl_builtin_concat, state, arg0, arg1) {
|
||||
strcat(outstr, arg0->string);
|
||||
strcat(outstr, arg1->string);
|
||||
|
||||
return ucl_string_create(outstr);
|
||||
struct ucl_object *result = ucl_string_create(outstr);
|
||||
free(outstr);
|
||||
return result;
|
||||
}
|
||||
|
||||
LISP_FUNC_0(ucl_builtin_now_millis_mono, state) {
|
||||
@@ -146,6 +151,47 @@ LISP_FUNC_0(ucl_builtin_now_millis_mono, state) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ucl_print_obj(struct ucl_object *obj) {
|
||||
switch (obj->type) {
|
||||
case UCL_TYPE_SYMBOL:
|
||||
printf("%s", obj->symbol);
|
||||
break;
|
||||
case UCL_TYPE_INT:
|
||||
printf("%d", obj->integer);
|
||||
break;
|
||||
case UCL_TYPE_STRING:
|
||||
printf("\"%s\"", obj->string);
|
||||
break;
|
||||
case UCL_TYPE_ERROR:
|
||||
printf("(error \"%s\")", obj->error);
|
||||
break;
|
||||
case UCL_TYPE_BUILTIN:
|
||||
printf("<builtin %p>", obj->builtin);
|
||||
break;
|
||||
case UCL_TYPE_CELL: {
|
||||
int first = true;
|
||||
printf("%s", "(");
|
||||
FOREACH_LIST(obj, iter, item) {
|
||||
if (!first) {
|
||||
printf(" ");
|
||||
}
|
||||
ucl_print_obj(item);
|
||||
first = false;
|
||||
}
|
||||
printf("%s", ")");
|
||||
break;
|
||||
}
|
||||
case UCL_TYPE_COUNT:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
LISP_FUNC_1(ucl_builtin_print, state, arg0) {
|
||||
ucl_print_obj(arg0);
|
||||
|
||||
return ucl_nil_create();
|
||||
}
|
||||
|
||||
struct ucl_object *ucl_builtin_let(struct ucl_state *state, struct ucl_object *args) {
|
||||
// TODO: Check arguments
|
||||
struct ucl_object *assignments = ucl_car(args);
|
||||
@@ -180,3 +226,12 @@ struct ucl_object *ucl_builtin_let(struct ucl_state *state, struct ucl_object *a
|
||||
ucl_state_delete(let_state);
|
||||
return result;
|
||||
}
|
||||
|
||||
struct ucl_object *ucl_builtin_list(struct ucl_state *state, struct ucl_object *args) {
|
||||
struct ucl_object *head = ucl_nil_create();
|
||||
FOREACH_LIST(args, iter, item) {
|
||||
ucl_list_append(head, item);
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
@@ -63,5 +63,7 @@ struct ucl_object *ucl_builtin_concat(struct ucl_state *state, struct ucl_object
|
||||
struct ucl_object *ucl_builtin_now_millis_mono(struct ucl_state *state, struct ucl_object *args);
|
||||
|
||||
struct ucl_object *ucl_builtin_let(struct ucl_state *state, struct ucl_object *args);
|
||||
struct ucl_object *ucl_builtin_list(struct ucl_state *state, struct ucl_object *args);
|
||||
struct ucl_object *ucl_builtin_print(struct ucl_state *state, struct ucl_object *args);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
#include <string.h>
|
||||
|
||||
struct ucl_object *ucl_evaluate_list(struct ucl_state *state, struct ucl_object *list) {
|
||||
if (list->cell.car == NULL) {
|
||||
return list;
|
||||
}
|
||||
|
||||
// TODO: Recursively eval args
|
||||
struct ucl_object *evaluated_list = ucl_nil_create();
|
||||
|
||||
|
||||
18
src/main.c
18
src/main.c
@@ -12,6 +12,8 @@ int main(int argc, const char **argv) {
|
||||
struct ucl_state *state = ucl_state_create();
|
||||
|
||||
ucl_state_put(state, "let", ucl_builtin_create(ucl_builtin_let));
|
||||
ucl_state_put(state, "print", ucl_builtin_create(ucl_builtin_print));
|
||||
ucl_state_put(state, "list", ucl_builtin_create(ucl_builtin_list));
|
||||
|
||||
ucl_state_put(state, "+", ucl_builtin_create(ucl_builtin_add));
|
||||
ucl_state_put(state, "-", ucl_builtin_create(ucl_builtin_sub));
|
||||
@@ -31,19 +33,9 @@ int main(int argc, const char **argv) {
|
||||
struct ucl_object *sexp = ucl_parse(argv[1]);
|
||||
struct ucl_object *result = ucl_evaluate(state, ucl_car(sexp));
|
||||
|
||||
switch (result->type) {
|
||||
case UCL_TYPE_INT:
|
||||
printf("%d\n", result->integer);
|
||||
break;
|
||||
case UCL_TYPE_STRING:
|
||||
printf("\"%s\"\n", result->string);
|
||||
break;
|
||||
case UCL_TYPE_SYMBOL:
|
||||
printf("%s\n", result->string);
|
||||
break;
|
||||
case UCL_TYPE_ERROR:
|
||||
printf("ERROR: %s\n", result->error);
|
||||
return 1;
|
||||
if (result->type == UCL_TYPE_ERROR) {
|
||||
printf("%s", result->error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -34,7 +34,8 @@ struct ucl_object *ucl_state_get(struct ucl_state *state, const char *name) {
|
||||
struct ucl_object *cell = ucl_state_get_cell(state, name);
|
||||
if (cell == NULL) {
|
||||
if (state->parent == NULL) {
|
||||
return ucl_error_create("Unknown error");
|
||||
// TODO: Include the symbol name
|
||||
return ucl_error_create("Unbound symbol");
|
||||
} else {
|
||||
return ucl_state_get(state->parent, name);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ void setUp(void) {
|
||||
ucl_state_put(state, "let", ucl_builtin_create(ucl_builtin_let));
|
||||
ucl_state_put(state, "+", ucl_builtin_create(ucl_builtin_add));
|
||||
ucl_state_put(state, "error", ucl_builtin_create(ucl_builtin_error));
|
||||
ucl_state_put(state, "list", ucl_builtin_create(ucl_builtin_list));
|
||||
}
|
||||
|
||||
void tearDown(void) {
|
||||
@@ -108,6 +109,18 @@ static void test_eval_nested_error(void) {
|
||||
TEST_ASSERT_OBJ_ERROR(response);
|
||||
}
|
||||
|
||||
static void test_eval_list(void) {
|
||||
response = eval("(list 1 2 3)");
|
||||
TEST_ASSERT_OBJ_LIST(response);
|
||||
TEST_ASSERT_EQUAL(ucl_list_length(response)->integer, 3);
|
||||
|
||||
int i = 1;
|
||||
FOREACH_LIST(response, iter, item) {
|
||||
TEST_ASSERT_EQUAL(item->integer, i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(void) {
|
||||
UNITY_BEGIN();
|
||||
@@ -124,6 +137,7 @@ int main(void) {
|
||||
RUN_TEST(test_eval_sym_defined);
|
||||
RUN_TEST(test_eval_sym_undefined);
|
||||
RUN_TEST(test_eval_nested_error);
|
||||
RUN_TEST(test_eval_list);
|
||||
|
||||
return UNITY_END();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user