Add defun without evaluation
This commit is contained in:
86
src/special.c
Normal file
86
src/special.c
Normal file
@@ -0,0 +1,86 @@
|
||||
#include "state.h"
|
||||
#include "lisp.h"
|
||||
#include "utility.h"
|
||||
#include "internal.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
struct ucl_object *ucl_special_let(struct ucl_state *state, struct ucl_object *args) {
|
||||
// TODO: Check arguments
|
||||
struct ucl_object *assignments = ucl_car(args);
|
||||
struct ucl_object *expressions = ucl_cdr(args);
|
||||
struct ucl_state *let_state = ucl_state_create_child(state);
|
||||
|
||||
FOREACH_LIST(assignments, iter, item) {
|
||||
// TODO: Check arguments
|
||||
struct ucl_object *sym = ucl_car(item);
|
||||
struct ucl_object *expr = ucl_car(ucl_cdr(item));
|
||||
struct ucl_object *value = ucl_evaluate(let_state, expr);
|
||||
|
||||
assert(sym->type == UCL_TYPE_SYMBOL);
|
||||
//assert(ucl_list_length(expr)->integer == 1);
|
||||
|
||||
if (value->type == UCL_TYPE_ERROR) {
|
||||
// TODO cleanup
|
||||
return value;
|
||||
}
|
||||
ucl_state_put(let_state, sym->symbol, value);
|
||||
}
|
||||
|
||||
struct ucl_object *result = NULL;
|
||||
FOREACH_LIST(expressions, iter, item) {
|
||||
result = ucl_evaluate(let_state, item);
|
||||
if (result->type == UCL_TYPE_ERROR) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ucl_state_delete(let_state);
|
||||
return result;
|
||||
}
|
||||
|
||||
struct ucl_object *ucl_special_if(struct ucl_state *state, struct ucl_object *args) {
|
||||
// TODO: Check arguments
|
||||
struct ucl_object *cond = ucl_car(args);
|
||||
struct ucl_object *true_form = ucl_list_nth(args, 1);
|
||||
struct ucl_object *false_forms = ucl_cdr(ucl_cdr(args));
|
||||
|
||||
struct ucl_object *cond_result = ucl_evaluate(state, cond);
|
||||
UCL_RET_IF_ERROR(cond_result);
|
||||
if (ucl_truthy(cond_result)->type == UCL_TYPE_SYMBOL) {
|
||||
return ucl_evaluate(state, true_form);
|
||||
}
|
||||
|
||||
struct ucl_object *result = NULL;
|
||||
|
||||
FOREACH_LIST(false_forms, iter, form) {
|
||||
result = ucl_evaluate(state, form);
|
||||
}
|
||||
|
||||
return (result == NULL) ? ucl_nil_create() : result;
|
||||
}
|
||||
|
||||
|
||||
struct ucl_object *ucl_special_defun(struct ucl_state *state, struct ucl_object *args) {
|
||||
// TODO: Check arguments
|
||||
struct ucl_object *fun_sym = ucl_car(args);
|
||||
if (fun_sym->type != UCL_TYPE_SYMBOL) {
|
||||
return ucl_error_create("First argument to defun must be a symbol");
|
||||
}
|
||||
|
||||
struct ucl_object *fun_args = ucl_list_nth(args, 1);
|
||||
if (fun_args->type != UCL_TYPE_CELL) {
|
||||
// TODO: Check that the list contains only symbols
|
||||
return ucl_error_create("Second argument to defun must be a list of symbols");
|
||||
}
|
||||
|
||||
// For now, other elements are just forms to be evaluated. Maybe one day
|
||||
// there will be docstrings, maybe not!
|
||||
|
||||
// Functions are added to the root scope
|
||||
ucl_state_put(ucl_state_get_root(state), fun_sym->symbol, ucl_cdr(args));
|
||||
|
||||
return fun_sym;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user