aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md5
-rw-r--r--files/test-lambda.l14
-rw-r--r--src/common.h2
-rw-r--r--src/env.c75
-rw-r--r--src/env.h5
-rw-r--r--src/hamt.c337
-rw-r--r--src/hamt.h45
-rw-r--r--src/lexer.c59
-rw-r--r--src/lexer.h10
-rw-r--r--src/main.c68
-rw-r--r--src/value.c56
-rw-r--r--src/value.h6
12 files changed, 193 insertions, 489 deletions
diff --git a/README.md b/README.md
index 8170398..98c6004 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,9 @@
-g### nlisp
+### nlisp
A simple lisp/scheme interpreter
#### TODO
-* hamt for allocations
-
* reduce allocations
-* overhaul environement/closures
* improve errors
* FFI
diff --git a/files/test-lambda.l b/files/test-lambda.l
index d58169a..3136452 100644
--- a/files/test-lambda.l
+++ b/files/test-lambda.l
@@ -92,3 +92,17 @@
(cond (((= 1 2) 3)
((= 1 (+ 1 1)) (+ 6 2))
(1 (quote test))))
+
+(defmacro begin (vars)
+ (foldr (lambda (var rest) `((lambda (__) ,rest) ,var)) '__ vars))
+
+(begin
+ ((define inc (lambda (a) (+ a 1)))
+ (inc 1)))
+
+(define inc (lambda (a) (+ a 1)))
+
+(begin
+ ((+ 0 1)
+ (define a inc)))
+ ;; (a 1)))
diff --git a/src/common.h b/src/common.h
index 225f217..4f580b9 100644
--- a/src/common.h
+++ b/src/common.h
@@ -47,6 +47,8 @@ static inline char *timenow(void)
#include <errno.h>
+#define NOT_IMPLEMENTED() die("Not Implemented. ABORTING")
+
#define ERR_NZ(e, r, on_fail) do { \
int r; \
if((r = e)) { on_fail; } \
diff --git a/src/env.c b/src/env.c
index ee2e65e..840b87c 100644
--- a/src/env.c
+++ b/src/env.c
@@ -25,9 +25,21 @@ struct env_kv {
int flags;
};
-#include "mempool.h"
-MEMPOOL_GENERATE(env, struct env, 256)
-MEMPOOL_GENERATE(env_kv, struct env_kv, 1024)
+// #ifdef ENABLE_MEMPOOL
+ #include "mempool.h"
+ MEMPOOL_GENERATE(env, struct env, 256)
+ MEMPOOL_GENERATE(env_kv, struct env_kv, 1024)
+
+ #define env_alloc() env_mempool_allocate()
+ #define env_free(v) env_mempool_free(v)
+ #define env_kv_alloc() env_kv_mempool_allocate()
+ #define env_kv_free(v) env_kv_mempool_free(v)
+// #else
+ // #define env_alloc() malloc(sizeof(struct env))
+ // #define env_free(v) free(v)
+ // #define env_kv_alloc() malloc(sizeof(struct env_kv))
+ // #define env_kv_free(v) free(v)
+// #endif
static int equal(char *key1, char *key2)
{
@@ -36,7 +48,7 @@ static int equal(char *key1, char *key2)
static struct env_kv *env_kv_create(char *key, value_t value, int flags)
{
- struct env_kv *pair = env_kv_mempool_allocate();
+ struct env_kv *pair = env_kv_alloc();
pair->key = key;
pair->value = value;
@@ -52,12 +64,12 @@ static void env_kv_destroy(struct env_kv *pair)
free(pair->key);
value_destroy(pair->value);
- env_kv_mempool_free(pair);
+ env_kv_free(pair);
}
env_t env_create(env_t parent)
{
- env_t env = env_mempool_allocate();
+ env_t env = env_alloc();
env->parent = env_copy(parent);
env->head = NULL;
@@ -83,7 +95,7 @@ void env_destroy(env_t env)
}
env_destroy(env->parent);
- env_mempool_free(env);
+ env_free(env);
}
int env_insert(env_t env, char *key, _value_t value,
@@ -139,18 +151,37 @@ env_t env_copy(env_t env)
return env;
}
-// void env_print(env_t env)
-// {
-// printf("REFS: %d\n", env->refs);
-// printf("CREFS: %d\n", env->circular_refs);
-// if(!env || !env->head) return;
-// list_for_each_entry(struct env_kv, pair, list, env->head) {
-// printf("ENTRY: %s %s\n", pair->key, pair->value);
-// }
-
-// if(env->parent) {
-// printf("---- PARENT ----\n");
-// env_print(env->parent);
-// printf("-- END PARENT --\n");
-// }
-// }
+int env_depend(env_t parent, env_t dep)
+{
+ if(!dep || !parent) return 0;
+ if(dep == parent) return 1;
+
+ return env_depend(parent, dep->parent);
+}
+
+#ifdef DEBUG
+static void _env_print(env_t env, int depth)
+{
+ (void)depth;
+
+ printf("refs: %d\n", env->refs);
+ printf("crefs: %d\n", env->circular_refs);
+ if(!env || !env->head) return;
+ list_for_each_entry(struct env_kv, pair, list, env->head) {
+ printf(" %s %s\n", pair->key, pair->value);
+ }
+
+ if(env->parent) {
+ printf("--- parent start ---\n");
+ _env_print(env->parent, depth+2);
+ printf("---- parent end ----\n");
+ }
+}
+
+void env_print(env_t env)
+{
+ printf("--- env start ---\n");
+ _env_print(env, 0);
+ printf("---- env end ----\n");
+}
+#endif
diff --git a/src/env.h b/src/env.h
index 3415410..7d4ceac 100644
--- a/src/env.h
+++ b/src/env.h
@@ -22,5 +22,10 @@ int env_insert(env_t env, char *key, _value_t value,
int env_query(env_t env, char *key, _value_t *data);
env_t env_copy(env_t env);
+int env_depend(env_t parent, env_t dep);
+
+#ifdef DEBUG
+void env_print(env_t env);
+#endif
#endif
diff --git a/src/hamt.c b/src/hamt.c
deleted file mode 100644
index a6be3ba..0000000
--- a/src/hamt.c
+++ /dev/null
@@ -1,337 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <assert.h>
-#include "hamt.h"
-
-#include "mempool.h"
-MEMPOOL_GENERATE(hamt, struct hamt, 16)
-MEMPOOL_GENERATE(hl, struct hamt_nodelist, 64)
-MEMPOOL_GENERATE(hi, struct hamt_item, 32)
-
-#define tag_ptr(ptr, tag) ((uintptr_t)(ptr) | (tag))
-#define untag_ptr(ptr, tag) ((uintptr_t)(ptr) & ~(tag))
-#define is_tagged(ptr, tag) ((uintptr_t)(ptr) & (tag))
-
-#define HAMT_ITEM_TAG 0x1
-#define TAG_NODELIST(ptr) \
- (hamtptr_t)untag_ptr(ptr, HAMT_ITEM_TAG)
-#define TAG_ITEM(ptr) \
- (hamtptr_t)tag_ptr(ptr, HAMT_ITEM_TAG)
-#define AS_NODELIST(ptr) \
- ((struct hamt_nodelist *)untag_ptr(ptr, HAMT_ITEM_TAG))
-#define AS_ITEM(ptr) \
- ((struct hamt_item *)untag_ptr(ptr, HAMT_ITEM_TAG))
-#define AS_VOIDPTR(ptr) \
- ((void *)untag_ptr(ptr, HAMT_ITEM_TAG)
-#define IS_NODELIST(hamtptr) \
- !is_tagged(hamtptr, HAMT_ITEM_TAG)
-#define IS_ITEM(hamtptr) \
- is_tagged(hamtptr, HAMT_ITEM_TAG)
-
-#define for_each_item(item, head) \
- for(struct hamt_item *item = (head), *next = NULL; \
- item && (next = item->next, 1); item = next)
-
-#define popcount(i) __builtin_popcount(i)
-
-#define BITS 6
-#define BITS_MASK 0x3f
-
-static inline struct hamt_nodelist *hamt_nodelist_alloc(void);
-static inline struct hamt_item *hamt_item_alloc(void);
-
-static void hamtptr_destroy(hamtptr_t hamtptr);
-static inline void hamtptr_add_ref(hamtptr_t hamtptr);
-
-// static void hamt_print_hamtptr(hamtptr_t hamtptr, int depth);
-
-hamt_t hamt_create(hamt_equal_fn equal_fn, hamt_hash_fn hash_fn)
-{
- // hamt_t hamt = malloc(sizeof(*hamt));
- hamt_t hamt = hamt_mempool_allocate();
- hamt->equal_fn = equal_fn;
- hamt->hash_fn = hash_fn;
- hamt->root = TAG_NODELIST(hamt_nodelist_alloc());
-
- return hamt;
-}
-
-void hamt_destroy(hamt_t hamt)
-{
- if(!hamt) return;
-
- hamtptr_destroy(hamt->root);
- // free(hamt);
- hamt_mempool_free(hamt);
-}
-
-hamt_t hamt_clone(hamt_t src)
-{
- // hamt_t hamt = malloc(sizeof(*hamt));
- hamt_t hamt = hamt_mempool_allocate();
-
- if(!src) return hamt;
-
- hamt->equal_fn = src->equal_fn;
- hamt->hash_fn = src->hash_fn;
- hamt->root = src->root;
- hamtptr_add_ref(hamt->root);
-
- return hamt;
-}
-
-static int hamt_find_hamtptr(hamtptr_t root, hamtptr_t *ret, uint32_t *hash)
-{
- *ret = root;
-
- for(size_t i = 0; i < sizeof(*hash)*8/BITS; i++) {
- assert(IS_NODELIST(*ret));
- struct hamt_nodelist *nodelist = AS_NODELIST(*ret);
-
- size_t rawidx = *hash & BITS_MASK;
- if(!(nodelist->bitmask & (1 << rawidx))) {
- return sizeof(*hash)*8/BITS - i;
- }
-
- *hash >>= BITS;
-
- size_t idx = popcount(nodelist->bitmask & ((1 << rawidx) - 1));
- *ret = nodelist->list[idx];
- }
-
- return 0;
-}
-
-int hamt_get(hamt_t hamt, void *key, void **data)
-{
- hamtptr_t hamtptr;
- uint32_t hash = hamt->hash_fn(key);
-
- if(hamt_find_hamtptr(hamt->root, &hamtptr, &hash) != 0)
- return 1;
-
- assert(IS_ITEM(hamtptr));
- struct hamt_item *item = AS_ITEM(hamtptr);
-
- while(!hamt->equal_fn(key, item->key)) {
- if(item->next == NULL) return 1;
- item = item->next;
- }
-
- *data = item->data;
- return 0;
-}
-
-static hamtptr_t hamt_build(uint32_t hash, size_t iter, struct hamt_item **item)
-{
- if(iter == 1) {
- *item = hamt_item_alloc();
- return TAG_ITEM(*item);
- }
-
- hash >>= BITS;
- size_t next_idx = hash & BITS_MASK;
-
- hamtptr_t next = hamt_build(hash, iter-1, item);
-
- struct hamt_nodelist *nodelist = hamt_nodelist_alloc();
-
- // nodelist->list = &next;
- nodelist->list = calloc(1, sizeof(*nodelist->list));
- nodelist->list[0] = next;
-
- nodelist->bitmask = 1 << next_idx;
-
- return TAG_NODELIST(nodelist);
-}
-
-static hamtptr_t hamt_insert_hamtptr(hamtptr_t root, hamtptr_t hamtptr, uint32_t hash, hamt_equal_fn equal_fn)
-{
- if(IS_ITEM(root)) {
- struct hamt_item *item = AS_ITEM(root);
-
- if(equal_fn(item->key, AS_ITEM(hamtptr)->key)) {
- item->refs--;
- AS_ITEM(hamtptr)->next = item->next;
- return hamtptr;
- }
-
- if(item->next) {
- hamtptr = hamt_insert_hamtptr(TAG_ITEM(item->next), hamtptr, hash, equal_fn);
- }
-
- struct hamt_item *new;
-
- if(item->refs == 1) {
- new = item;
- } else {
- item->refs--;
- new = hamt_item_alloc();
- new->key = item->key;
- new->data = item->data;
- }
-
- new->next = AS_ITEM(hamtptr);
- return TAG_ITEM(new);
- }
-
- struct hamt_nodelist *nodelist = AS_NODELIST(root);
-
- size_t rawidx = hash & BITS_MASK;
- size_t idx = popcount(nodelist->bitmask & ((1 << rawidx) - 1));
-
- size_t list_len = popcount(nodelist->bitmask);
- size_t newlist_len = list_len;
-
- if(nodelist->bitmask & (1 << rawidx)) {
- hamtptr = hamt_insert_hamtptr(nodelist->list[idx], hamtptr, hash >> BITS, equal_fn);
-
- if(nodelist->refs == 1) {
- nodelist->list[idx] = hamtptr;
- return TAG_NODELIST(nodelist);
- }
- } else {
- newlist_len++;
- }
-
- hamtptr_t *newlist = calloc(newlist_len, sizeof(*newlist));
- newlist[idx] = hamtptr;
-
- for(size_t i = 0; i < idx; i++)
- newlist[i] = nodelist->list[i];
-
- if(list_len == newlist_len)
- for(size_t i = idx+1; i < newlist_len; i++)
- newlist[i] = nodelist->list[i];
- else
- for(size_t i = idx+1; i < newlist_len; i++)
- newlist[i] = nodelist->list[i-1];
-
- struct hamt_nodelist *new;
-
- if(nodelist->refs == 1) {
- new = nodelist;
- free(nodelist->list);
- } else {
- nodelist->refs--;
- new = hamt_nodelist_alloc();
- }
-
- new->list = newlist;
- new->bitmask = nodelist->bitmask | (1 << rawidx);
- return TAG_NODELIST(new);
-}
-
-int hamt_set(hamt_t hamt, void *key, void *data, void **keyptr, void **prevdata)
-{
- hamtptr_t hamtptr;
- uint32_t hash = hamt->hash_fn(key);
- uint32_t hash_cpy = hash;
-
- size_t iter;
- if((iter = hamt_find_hamtptr(hamt->root, &hamtptr, &hash_cpy)) != 0) {
- struct hamt_item *item;
- hamtptr_t new = hamt_build(hash_cpy, iter, &item);
-
- hamt->root = hamt_insert_hamtptr(hamt->root, new, hash, hamt->equal_fn);
-
- item->key = key;
- item->data = data;
- return 0;
- }
-
- assert(IS_ITEM(hamtptr));
-
- for_each_item(item, AS_ITEM(hamtptr)) {
- if(hamt->equal_fn(item->key, key)) {
- if(keyptr) *keyptr = item->key;
- if(prevdata) *prevdata = item->data;
- if(item->refs == 1) {
- item->data = data;
- return 0;
- }
-
- key = item->key;
- break;
- }
- }
-
- struct hamt_item *new = hamt_item_alloc();
- new->key = key;
- new->data = data;
-
- hamt->root = hamt_insert_hamtptr(hamt->root, TAG_ITEM(new), hash, hamt->equal_fn);
- return 0;
-}
-
-static inline struct hamt_nodelist *hamt_nodelist_alloc(void)
-{
- // struct hamt_nodelist *nodelist = malloc(sizeof(*nodelist));
- struct hamt_nodelist *nodelist = hl_mempool_allocate();
- nodelist->refs = 1;
- nodelist->list = 0;
- nodelist->bitmask = 0;
- return nodelist;
-}
-
-static inline struct hamt_item *hamt_item_alloc(void)
-{
- // struct hamt_item *item = malloc(sizeof(*item));
- struct hamt_item *item = hi_mempool_allocate();
- item->refs = 1;
- item->key = NULL;
- item->data = NULL;
- item->next = NULL;
- return item;
-}
-
-static inline void hamtptr_destroy(hamtptr_t hamtptr)
-{
- if(IS_NODELIST(hamtptr)) {
- struct hamt_nodelist *nodelist = AS_NODELIST(hamtptr);
-
- for(size_t i = 0; i < popcount(nodelist->bitmask); i++)
- hamtptr_destroy(nodelist->list[i]);
-
- if(--nodelist->refs == 0) {
- free(nodelist->list);
- // free(nodelist);
- hl_mempool_free(nodelist);
- }
- } else {
- for_each_item(item, AS_ITEM(hamtptr))
- if(--item->refs == 0)
- hi_mempool_free(item);
- // free(item);
- }
-}
-
-static inline void hamtptr_add_ref(hamtptr_t hamtptr)
-{
- if(IS_NODELIST(hamtptr)) {
- for(size_t i = 0; i < popcount(AS_NODELIST(hamtptr)->bitmask); i++)
- hamtptr_add_ref(AS_NODELIST(hamtptr)->list[i]);
- AS_NODELIST(hamtptr)->refs++;
- } else {
- for_each_item(item, AS_ITEM(hamtptr))
- item->refs++;
- }
-}
-
-// static void hamt_print_hamtptr(hamtptr_t hamtptr, int depth)
-// {
-// for(int i = 0; i < depth; i++) printf(" ");
-
-// if(IS_NODELIST(hamtptr)) {
-// printf("%d, MASK %b\n", AS_NODELIST(hamtptr)->refs, AS_NODELIST(hamtptr)->bitmask);
-// for(size_t i = 0; i < popcount(AS_NODELIST(hamtptr)->bitmask); i++) {
-// hamt_print_hamtptr(AS_NODELIST(hamtptr)->list[i], depth+1);
-// }
-// } else {
-// printf("%d, %s: %s\n", AS_ITEM(hamtptr)->refs, (char *)AS_ITEM(hamtptr)->key, (char *)AS_ITEM(hamtptr)->data);
-// if(AS_ITEM(hamtptr)->next)
-// hamt_print_hamtptr(TAG_ITEM(AS_ITEM(hamtptr)->next), depth+1);
-// }
-// }
diff --git a/src/hamt.h b/src/hamt.h
deleted file mode 100644
index 6ef27ba..0000000
--- a/src/hamt.h
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef HAMT_H
-#define HAMT_H
-
-#include <stdint.h>
-
-typedef struct hamt *hamt_t;
-
-// tagged pointer to either
-// hamt_item or hamt_nodelist
-typedef uintptr_t hamtptr_t;
-
-struct hamt_item {
- uint32_t refs;
-
- void *key;
- void *data;
- struct hamt_item *next;
-};
-
-struct hamt_nodelist {
- uint32_t refs;
-
- uint64_t bitmask;
- hamtptr_t *list;
-};
-
-typedef int (*hamt_equal_fn)(void *key1, void *key2);
-typedef uint32_t (*hamt_hash_fn)(void *key);
-
-struct hamt {
- hamt_equal_fn equal_fn;
- hamt_hash_fn hash_fn;
-
- hamtptr_t root;
-};
-
-hamt_t hamt_create(hamt_equal_fn equal_fn, hamt_hash_fn hash_fn);
-void hamt_destroy(hamt_t hamt);
-
-hamt_t hamt_clone(hamt_t src);
-
-int hamt_get(hamt_t hamt, void *key, void **data);
-int hamt_set(hamt_t hamt, void *key, void *data, void **keyptr, void **prevdata);
-
-#endif
diff --git a/src/lexer.c b/src/lexer.c
index cd83006..29e084c 100644
--- a/src/lexer.c
+++ b/src/lexer.c
@@ -133,11 +133,22 @@ int token_value_string(struct token *token, size_t buf_sz, char *buf)
return 0;
}
-#define STR_ALLOC_COPY(dest, str) do { \
- size_t len = strlen(str) + 1; \
- dest = malloc(len); \
- memcpy((dest), (str), len); \
- } while(0)
+char *token_value_static_string(struct token *token)
+{
+ static char str[1024];
+
+ if(token_value_string(token, sizeof(str), str) > 0)
+ return str;
+ return NULL;
+}
+
+static char *str_alloc_copy(char *src)
+{
+ if(!src) return src;
+
+ size_t len = strlen(src) + 1;
+ return memcpy(malloc(len), src, len);
+}
void token_clone(struct token *dest, struct token *src)
{
@@ -145,10 +156,10 @@ void token_clone(struct token *dest, struct token *src)
switch(src->type) {
case TOKEN_ID:
- STR_ALLOC_COPY(dest->value.id, src->value.id);
+ dest->value.id = str_alloc_copy(src->value.id);
return;
case TOKEN_STR:
- STR_ALLOC_COPY(dest->value.str, src->value.str);
+ dest->value.str = str_alloc_copy(src->value.str);
return;
case TOKEN_INT:
dest->value.num = src->value.num;
@@ -170,7 +181,20 @@ void token_dealloc(struct token *token)
}
}
-void toklist_destroy(struct toklist *toklist)
+struct toklist *toklist_alloc(struct token *tokens, size_t tokens_len)
+{
+ struct toklist *toklist;
+ toklist = malloc(sizeof(*toklist));
+ LIST_EMPTY(&toklist->list);
+
+ toklist->tokens = calloc(tokens_len, sizeof(*tokens));
+ memcpy(toklist->tokens, tokens, tokens_len * sizeof(*tokens));
+ toklist->tokens_len = tokens_len;
+
+ return toklist;
+}
+
+void toklist_dealloc(struct toklist *toklist)
{
list_for_each_safe(head, &toklist->list) {
toklist = list_entry(head, struct toklist, list);
@@ -181,6 +205,25 @@ void toklist_destroy(struct toklist *toklist)
free(toklist);
}
}
+#ifdef DEBUG
+void token_print(struct token *token)
+{
+ printf("%-12s %s\n",
+ token_type_string[token->type],
+ token_value_static_string(token));
+}
+
+void toklist_print(struct toklist *toklist)
+{
+ printf("--- toklis start ---\n");
+ list_for_each(pos, &toklist->list) {
+ struct toklist *entry = list_entry(pos, struct toklist, list);
+ for(size_t i = 0; i < entry->tokens_len; i++)
+ token_print(&entry->tokens[i]);
+ }
+ printf("---- toklis end ----\n");
+}
+#endif
static int on_separator(lexer_t lexer, enum token_type type)
{
diff --git a/src/lexer.h b/src/lexer.h
index 632811e..0cbda75 100644
--- a/src/lexer.h
+++ b/src/lexer.h
@@ -68,9 +68,17 @@ int lexer_clear_line(lexer_t lexer);
int lexer_token_next(lexer_t lexer, struct token *token);
int token_value_string(struct token *token, size_t buf_sz, char *buf);
+char *token_value_static_string(struct token *token);
void token_clone(struct token *dest, struct token *src);
void token_dealloc(struct token *token);
-void toklist_destroy(struct toklist *toklist);
+
+struct toklist *toklist_alloc(struct token *tokens, size_t tokens_len);
+void toklist_dealloc(struct toklist *toklist);
+
+#ifdef DEBUG
+void token_print(struct token *token);
+void toklist_print(struct toklist *toklist);
+#endif
#endif
diff --git a/src/main.c b/src/main.c
index 70dd906..24dacc8 100644
--- a/src/main.c
+++ b/src/main.c
@@ -50,34 +50,6 @@
} while(0)
-#define NOT_IMPLEMENTED() die("Not Implemented. ABORTING")
-
-static void print_token(struct token *token)
-{
- char buf[256] = {0};
- ERR_Z(token_value_string(token, LEN(buf), buf), return);
- info("%-12s %s", token_type_string[token->type], buf);
-}
-
-static void print_value(value_t value)
-{
- char buf[256] = {0};
- value_string(value, sizeof(buf), buf);
- info("%-12s %s", value ?
- value_type_string[vvalue_type(value)] : "VALUE", buf);
-}
-
-static void print_toklist(struct toklist *toklist)
-{
- info("TOKLIST_START");
- list_for_each(pos, &toklist->list) {
- struct toklist *entry = list_entry(pos, struct toklist, list);
- for(size_t i = 0; i < entry->tokens_len; i++)
- print_token(&entry->tokens[i]);
- }
- info("TOKLIST_END");
-}
-
struct tctx {
enum tctx_type {
TCTX_LEXER,
@@ -313,7 +285,7 @@ static value_t apply_macro(env_t env, struct proc *proc, value_t *args)
ret = evaluate_expr(env, &tctx);
exit:
- if(toklist) toklist_destroy(toklist);
+ if(toklist) toklist_dealloc(toklist);
value_destroy(macro_ret);
return ret;
@@ -506,7 +478,7 @@ value_t evaluate_lambda(env_t env, struct tctx *tctx)
fail:
err("Procedure creation failed");
for(size_t i = 0; i < argc; i++) value_destroy(args[i]);
- if(body) toklist_destroy(body);
+ if(body) toklist_dealloc(body);
if(arg_keys) free(arg_keys);
return VALUE_EMPTY;
}
@@ -539,7 +511,13 @@ value_t evaluate_define(env_t env, struct tctx *tctx)
value_t prevval = VALUE_EMPTY;
int flags = ENV_KV_FREE_KEY;
- flags |= (vvalue_type(val) == VALUE_PROC) ? ENV_KV_CIRCULAR_REF : 0;
+
+ if(vvalue_type(val) == VALUE_PROC) {
+ flags |= (env == global_env ||
+ env_depend(env, vvalue_proc(val).parent_env))
+ ? ENV_KV_CIRCULAR_REF : 0;
+
+ }
ERR_NZ(
env_insert(env, key, val, &prevval, flags),
@@ -759,19 +737,6 @@ exit:
}
-static struct toklist *toklist_create(struct token *tokens, size_t tokens_len)
-{
- struct toklist *toklist;
- toklist = malloc(sizeof(*toklist));
- LIST_EMPTY(&toklist->list);
-
- toklist->tokens = calloc(tokens_len, sizeof(*tokens));
- memcpy(toklist->tokens, tokens, tokens_len * sizeof(*tokens));
- toklist->tokens_len = tokens_len;
-
- return toklist;
-}
-
#define IS_OP(token) (token->type == TOKEN_QUOTE || \
token->type == TOKEN_QUASI || \
token->type == TOKEN_UNQUOTE)
@@ -790,7 +755,7 @@ static int toklist_expr(struct tctx *tctx, struct toklist **toklist)
if(tokens_len >= LEN(tokens)) {
if(toklist) {
- tail = list_add(tail, &toklist_create(tokens, tokens_len)->list);
+ tail = list_add(tail, &toklist_alloc(tokens, tokens_len)->list);
}
tokens_len = 0;
}
@@ -799,7 +764,7 @@ static int toklist_expr(struct tctx *tctx, struct toklist **toklist)
else if(TOKEN(tctx)->type == TOKEN_RP) depth--;
// printf("%zu\n", depth);
- // print_token(TOKEN(tctx));
+ // token_print(TOKEN(tctx));
if(toklist)
token_clone(&tokens[tokens_len++], TOKEN(tctx));
@@ -807,7 +772,7 @@ static int toklist_expr(struct tctx *tctx, struct toklist **toklist)
} while(depth != 0 || IS_OP(TOKEN(tctx)));
if(toklist) {
- tail = list_add(tail, &toklist_create(tokens, tokens_len)->list);
+ tail = list_add(tail, &toklist_alloc(tokens, tokens_len)->list);
*toklist = list_entry(list_get_head(tail), struct toklist, list);
}
@@ -836,6 +801,9 @@ static struct toklist *value_to_toklist(value_t value)
} else if(strcmp(vvalue_atom(value), "'") == 0) {
SET_TOKEN_TYPE(&token, TOKEN_QUOTE);
break;
+ } else if(strcmp(vvalue_atom(value), "define") == 0) {
+ SET_TOKEN_TYPE(&token, TOKEN_DEFINE);
+ break;
}
SET_TOKEN_TYPE(&token, TOKEN_ID);
@@ -858,14 +826,14 @@ static struct toklist *value_to_toklist(value_t value)
return NULL;
}
- return toklist_create(&token, 1);
+ return toklist_alloc(&token, 1);
}
static struct list_head *add_token_toklist(enum token_type type, struct list_head *tail)
{
struct token token = {0};
token.type = type;
- return list_add(tail, &(toklist_create(&token, 1)->list));
+ return list_add(tail, &(toklist_alloc(&token, 1)->list));
}
static struct toklist *cons_to_toklist(value_t value)
@@ -902,6 +870,6 @@ static struct toklist *cons_to_toklist(value_t value)
return list_entry(list_get_head(tail), struct toklist, list);
fail:
err("Failed to turn value to toklist");
- toklist_destroy(list_entry(list_get_head(tail), struct toklist, list));
+ toklist_dealloc(list_entry(list_get_head(tail), struct toklist, list));
return NULL;
}
diff --git a/src/value.c b/src/value.c
index 94a7acd..547da96 100644
--- a/src/value.c
+++ b/src/value.c
@@ -1,21 +1,27 @@
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "value.h"
+
#include "lexer.h"
-#include "mempool.h"
-MEMPOOL_GENERATE(value, struct value, 64)
-#define NOT_IMPLEMENTED() die("Not Implemented. ABORTING")
+// #ifdef ENABLE_MEMPOOL
+ #include "mempool.h"
+ MEMPOOL_GENERATE(value, struct value, 64)
+ #define value_alloc() value_mempool_allocate()
+ #define value_free(v) value_mempool_free(v)
+// #else
+ // #define value_alloc() malloc(sizeof(struct value))
+ // #define value_free(v) free(v)
+// #endif
const char * const value_type_string[] = {
VALUE_TYPES(TO_STRING)
};
-#define VALUE(_value) (_value)->value
-
#define FN(fn, ...) return fn(buf, buf_sz, __VA_ARGS__)
#define VALUE_STRING_TABLE(X, v, buf, buf_sz) \
X(VALUE_NIL, FN(snprintf, "(nil)")) \
@@ -34,9 +40,9 @@ const char * const value_type_string[] = {
X(VALUE_ATOM, if(NOREFS(v)) free(vvalue_atom(v))) \
X(VALUE_STR, if(NOREFS(v)) free(vvalue_str(v))) \
X(VALUE_INT, (void)NOREFS(v)) \
- X(VALUE_CONS, (void)NOREFS(v); \
+ X(VALUE_CONS, if(NOREFS(v)) { \
value_destroy(vvalue_cons(v).left); \
- value_destroy(vvalue_cons(v).right)) \
+ value_destroy(vvalue_cons(v).right);}) \
X(VALUE_PROC, if(NOREFS(v)) proc_destroy(&vvalue_proc(v))) \
X(VALUE_MACRO, if(NOREFS(v)) proc_destroy(&vvalue_proc(v))) \
X(VALUE_PROC_BUILTIN, (void)NOREFS(v))
@@ -63,12 +69,6 @@ const char * const value_type_string[] = {
X(VALUE_MACRO, proc) \
X(VALUE_PROC_BUILTIN, proc_builtin)
-// #define value_alloc() malloc(sizeof(struct value))
-// #define value_dealloc(v) free(v)
-#define value_alloc() value_mempool_allocate()
-#define value_free(v) value_mempool_free(v)
-
-
static char *str_alloc_copy(char *src);
static int cons_print(char *buf, size_t buf_sz, struct cons *cons);
@@ -123,14 +123,8 @@ value_t value_from_token(struct token *token)
value_t value_copy(value_t value)
{
if(!value) return value;
-
+
value_inc_refs(value);
-
- if(vvalue_type(value) == VALUE_CONS) {
- value_copy(vvalue_cons(value).left);
- value_copy(vvalue_cons(value).right);
- }
-
return value;
}
@@ -145,6 +139,24 @@ int value_string(value_t value, size_t buf_sz, char *buf)
return 0;
}
+char *value_static_string(value_t value)
+{
+ static char str[1024] = {0};
+
+ if(value_string(value, sizeof(str), str) > 0)
+ return str;
+ return NULL;
+}
+
+#ifdef DEBUG
+void value_print(value_t value)
+{
+ printf("%-12s %s", value ?
+ value_type_string[vvalue_type(value)] : "",
+ value_static_string(value));
+}
+#endif
+
static char *str_alloc_copy(char *src)
{
if(!src) return src;
@@ -204,10 +216,10 @@ exit:
static int proc_print(char *buf, size_t buf_sz, struct proc *proc)
{
- return 0;
(void)buf; (void)buf_sz;
(void)proc;
NOT_IMPLEMENTED();
+ return 0;
}
static void proc_destroy(struct proc *proc)
@@ -215,6 +227,6 @@ static void proc_destroy(struct proc *proc)
for(size_t i = 0; i < proc->argc; i++) value_destroy(proc->arg_keys[i]);
free(proc->arg_keys);
- toklist_destroy(proc->body);
+ toklist_dealloc(proc->body);
env_destroy(proc->parent_env);
}
diff --git a/src/value.h b/src/value.h
index f5f66d3..48d178c 100644
--- a/src/value.h
+++ b/src/value.h
@@ -77,6 +77,12 @@ void value_destroy(value_t value);
value_t value_from_token(struct token *token);
value_t value_copy(value_t value);
+
int value_string(value_t value, size_t buf_sz, char *buf);
+char *value_static_string(value_t value);
+
+#ifdef DEBUG
+void value_print(value_t value);
+#endif
#endif