#include "object.h" #include "ast.h" #include "hmap.h" #include "vector.h" #include #include #include static const char *object_types[] = { "error", "null", "int", "bool", "return", }; static void environment_destroy_cb(const void *key, void *val) { struct object *obj = val; object_unref(obj); } static inline char * bool_sprint(bool val, char *str) { sprintf(str, val ? "true" : "false"); return str; } extern inline const char * object_type_print(enum object_type type) { return object_types[type]; } static inline char * object_func_sprint(struct object *obj, char *str) { char *cur = str; sprintf(cur, "fn("); cur += strlen(cur); size_t i; struct expression *ident; vector_foreach(obj->func.params, i, ident) { node_sprint(ident, cur); cur += strlen(cur); if (i < (obj->func.params->len - 1)) { cur[0] = ',', cur[1] = ' ', cur += 2; } } sprintf(cur, ") {\n"); cur += strlen(cur); node_sprint(obj->func.body, cur); cur += strlen(cur); sprintf(cur, "\n}"); return str; } char * object_sprint(struct object *obj, char *str) { switch (obj->type) { case OBJECT_NULL: sprintf(str, "null"); break; case OBJECT_BOOL: return bool_sprint(obj->boolean, str); case OBJECT_INT: sprintf(str, "%ld", obj->integer); break; case OBJECT_RETURN: object_sprint(obj->retrn.value, str); case OBJECT_ERROR: strcpy(str, obj->error.msg); case OBJECT_FUNC: return object_func_sprint(obj, str); } return str; } struct object * object_new_int(int64_t val) { struct object *obj = malloc(sizeof(*obj)); obj->type = OBJECT_INT; obj->refcount = 1; obj->integer = val; return obj; } struct object * object_new_error(char *msg) { struct object *obj = malloc(sizeof(*obj)); obj->type = OBJECT_ERROR; obj->refcount = 1; obj->error.msg = msg; return obj; } struct object * object_new_return(struct object *val) { struct object *obj = malloc(sizeof(*obj)); obj->type = OBJECT_RETURN; obj->refcount = 1; obj->retrn.value = val; return obj; } struct object * object_new_func(struct expression *expr) { struct object *obj = malloc(sizeof(*obj)); obj->type = OBJECT_FUNC; obj->refcount = 1; obj->func.body = node_dup(expr->func.body); obj->func.params = expression_vector_dup(expr->func.parameters); return obj; } void object_ref(struct object *obj) { obj->refcount++; } void object_unref(struct object *obj) { if (obj->type == OBJECT_NULL || obj->type == OBJECT_BOOL) return; if (--obj->refcount < 1) { switch (obj->type) { case OBJECT_RETURN: object_unref(obj->retrn.value); break; case OBJECT_ERROR: free(obj->error.msg); break; case OBJECT_FUNC: node_destroy(obj->func.body); size_t i; struct expression *param; vector_foreach(obj->func.params, i, param) { node_destroy(param); } vector_free(obj->func.params); break; default: break; } free(obj); } } struct environment * environment_new_enclosed(struct environment *outer) { struct environment *env = malloc(sizeof(*env)); env->store = hmap_new(); if (!env->store) { free(env); return NULL; } env->outer = outer; return env; } struct object * environment_set(struct environment *env, struct slice key, struct object *val) { object_ref(val); return hmap_sets(env->store, key, val); } struct object * environment_get(struct environment *env, const struct slice *key) { struct object *obj = hmap_gets(env->store, key); if (!obj && env->outer) { obj = environment_get(env->outer, key); } return obj; } void environment_destroy(struct environment *env) { hmap_destroy(env->store, environment_destroy_cb); free(env); }