#include #include #include #include #include "desc.h" #include "khash.h" #include "mem.h" #include "thunk.h" // shorthand way to get the key from hashtable or null (0) if not found #define kh_get_val(kname, hash, key) ({k=kh_get(kname, hash, key);(k!=kh_end(hash)?kh_val(hash,k):0);}) // shorthand way to set value in hash with single line command. Returns value // returns 0=replaced existing item, 1=bucket empty (new key), 2-adding element previously deleted #define kh_set(kname, hash, key, val) ({int ret; k = kh_put(kname, hash,key,&ret); kh_value(hash,k) = val; ret;}) // name part of init must be unique for the key, value types. // in this instance 33 is arbitrary symbolic name for a hashtable // that contains string keys and void* values. const int khStrPtr = 33; KHASH_MAP_INIT_STR(khStrPtr, Desc*) // setup khash to handle string key with an arbitrary pointer payload // create a hashtable khash_t(khStrPtr) * funHash = kh_init(khStrPtr); void add_desc(char* fn, Desc* desc) { khiter_t k; // used by the macros kh_set(khStrPtr, funHash, fn, desc); } Desc* find_desc(char* fn) { khiter_t k; // used by the macros return kh_get_val(khStrPtr, funHash, fn); } Desc* get_slice(Desc* f, int nrargs) { assert(nrargs<=f->arity); return &(((SliceEntry*) f)[-(f->arity - nrargs)].base); } FunEntry* alloc_prim(char* name, int unboxable) { int len = strlen(name); FunEntry* entry = (FunEntry*) alloc_desc(sizeof (FunEntry) + len + 1); entry->base.type = FT_BOXED_LIT; entry->base.arity = 0; entry->base.thunk_size = sizeof(Thunk); entry->base.unboxable = unboxable; memcpy(entry->name, name, len + 1); return entry; } void gen_slices(SliceEntry* dest, Desc* forward_ptr, int arity) { for (int i = 0; i < arity; i++) { SliceEntry* slice = dest + i; slice->base.type = FT_SLICE; slice->base.arity = i; slice->base.thunk_size = thunk_size_f(i); slice->forward_ptr = forward_ptr; } } int printDesc(Desc* f) { switch (f->type) { case FT_SLICE: printDesc(((SliceEntry*) f)->forward_ptr); return f->arity; case FT_PRIM: printf("%s", ((PrimEntry*) f)->name); return f->arity; case FT_FUN: case FT_BOXED_LIT: printf("%s", ((FunEntry*) f)->name); return f->arity; case FT_ADT: printf("%s", ((ADTEntry*) f)->name); return f->arity; case FT_RECORD: printf("%s", ((RecordEntry*) f)->name); return f->arity; default: printf("printDesc: unhandled DESC %d\n", f->type); exit(-1); } } void init_desc() { __INT__ = alloc_prim("INT", 1); __BOOL__ = alloc_prim("BOOL", 1); __CHAR__ = alloc_prim("CHAR", 1); __REAL__ = alloc_prim("REAL", 1); __STRING__ = alloc_prim("STRING", 0); __ARRAY__ = alloc_prim("ARRAY", 0); __FORWARD_PTR__ = alloc_prim("FWD", 0); // Avoid to be overwritten by updateF __STACK_PLACEHOLDER__ = alloc_prim("PLACEHOLDER", 0); __STACK_PLACEHOLDER__->base.thunk_size = 0; } struct FunEntry* __INT__; struct FunEntry* __BOOL__; struct FunEntry* __CHAR__; struct FunEntry* __REAL__; struct FunEntry* __STRING__; struct FunEntry* __ARRAY__; struct FunEntry* __FORWARD_PTR__; struct FunEntry* __STACK_PLACEHOLDER__;