aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOskari Timperi <oskari.timperi@iki.fi>2014-05-15 22:50:37 +0300
committerOskari Timperi <oskari.timperi@iki.fi>2014-05-15 22:50:37 +0300
commita2ed9c63f26f5cd767ac6c1d4073cdaa08a168b4 (patch)
tree61402635148a26c8ab8a2fd51c0811dc258429a1
parente23d0ee6eec1433849e4af1f3906a0946a19aef4 (diff)
downloadlispish-a2ed9c63f26f5cd767ac6c1d4073cdaa08a168b4.tar.gz
lispish-a2ed9c63f26f5cd767ac6c1d4073cdaa08a168b4.zip
add atom_clone()
-rw-r--r--atom.c40
-rw-r--r--atom.h1
2 files changed, 41 insertions, 0 deletions
diff --git a/atom.c b/atom.c
index 375bd3e..cbcdbe8 100644
--- a/atom.c
+++ b/atom.c
@@ -44,6 +44,46 @@ struct atom *atom_new_list(struct list *list)
return atom;
}
+struct atom *atom_clone(struct atom *atom)
+{
+ switch (atom->type)
+ {
+ case ATOM_NIL:
+ case ATOM_TRUE:
+ case ATOM_FALSE:
+ return atom;
+
+ case ATOM_INT:
+ return atom_new_int(atom->l);
+
+ case ATOM_STR:
+ return atom_new_str(atom->str.str, atom->str.len);
+
+ case ATOM_SYMBOL:
+ return atom_new_sym(atom->str.str, atom->str.len);
+
+ case ATOM_LIST:
+ {
+ struct list *list = atom->list;
+ struct list *clone = NULL, *last = NULL;
+
+ while (list)
+ {
+ struct atom *a = LIST_GET_ATOM(list);
+ struct atom *b = atom_clone(a);
+ last = list_append(last, b);
+ list = list->next;
+ if (!clone)
+ clone = last;
+ }
+
+ return atom_new_list(clone);
+ }
+ }
+
+ return NULL;
+}
+
#ifdef BUILD_TEST
#include "test_util.h"
diff --git a/atom.h b/atom.h
index 62e3276..62f567a 100644
--- a/atom.h
+++ b/atom.h
@@ -54,6 +54,7 @@ struct atom *atom_new_int(long l);
struct atom *atom_new_str(const char *str, int len);
struct atom *atom_new_sym(const char *sym, int len);
struct atom *atom_new_list(struct list *list);
+struct atom *atom_clone();
extern struct atom true_atom;
extern struct atom false_atom;