#include #include "prim.h" #include "desc.h" #include "thunk.h" #include "mem.h" #define arg(idx) stack_a[stack_top_a - idx] void __addI(int dst_idx) { Thunk* target = get_dst(dst_idx); target->desc = (Desc*) __INT__; target->_int = readI(arg(2)) + readI(arg(1)); } void __subI(int dst_idx) { Thunk* target = get_dst(dst_idx); target->desc = (Desc*) __INT__; target->_int = readI(arg(2)) - readI(arg(1)); } void __multI(int dst_idx) { Thunk* target = get_dst(dst_idx); target->desc = (Desc*) __INT__; target->_int = readI(arg(2)) * readI(arg(1)); } void __divI(int dst_idx) { Thunk* target = get_dst(dst_idx); target->desc = (Desc*) __INT__; target->_int = readI(arg(2)) / readI(arg(1)); } void __gtI(int dst_idx) { Thunk* target = get_dst(dst_idx); target->desc = (Desc*) __BOOL__; target->_int = readI(arg(2)) > readI(arg(1)); } void __geI(int dst_idx) { Thunk* target = get_dst(dst_idx); target->desc = (Desc*) __BOOL__; target->_int = readI(arg(2)) >= readI(arg(1)); } void __ltI(int dst_idx) { Thunk* target = get_dst(dst_idx); target->desc = (Desc*) __BOOL__; target->_int = readI(arg(2)) < readI(arg(1)); } void __geC(int dst_idx) { Thunk* target = get_dst(dst_idx); target->desc = (Desc*) __BOOL__; target->_int = readC(arg(2)) >= readC(arg(1)); } void __eqI(int dst_idx) { Thunk* target = get_dst(dst_idx); target->desc = (Desc*) __BOOL__; target->_int = readI(arg(2)) == readI(arg(1)); } void __neqI(int dst_idx) { Thunk* target = get_dst(dst_idx); target->desc = (Desc*) __BOOL__; target->_int = readI(arg(2)) != readI(arg(1)); } void __eqB(int dst_idx) { Thunk* target = get_dst(dst_idx); target->desc = (Desc*) __BOOL__; target->_int = readB(arg(2)) == readB(arg(1)); } void __eqC(int dst_idx) { Thunk* target = get_dst(dst_idx); target->desc = (Desc*) __BOOL__; target->_int = readC(arg(2)) == readC(arg(1)); } void __not(int dst_idx) { Thunk* target = get_dst(dst_idx); target->desc = (Desc*) __BOOL__; target->_int = !readB(arg(1)); } void __and(int dst_idx) { Thunk* target = get_dst(dst_idx); target->desc = (Desc*) __BOOL__; target->_int = readB(arg(2)) && readB(arg(1)); } void __or(int dst_idx) { Thunk* target = get_dst(dst_idx); target->desc = (Desc*) __BOOL__; target->_int = readB(arg(2)) || readB(arg(1)); } void __mod(int dst_idx) { Thunk* target = get_dst(dst_idx); target->desc = (Desc*) __INT__; target->_int = readB(arg(2)) % readB(arg(1)); } void __C2I(int dst_idx) { Thunk* target = get_dst(dst_idx); target->desc = (Desc*) __INT__; target->_int = readC(arg(1)); } void __string_size(int dst_idx) { Thunk* target = get_dst(dst_idx); Thunk* arg = arg(1); int length; if(arg->desc == (Desc*) __STRING_PTR__) { length = arg->_string_ptr->length; } else { length = arg->_array.length; } target->desc = (Desc*) __INT__; target->_int = length; } void __string_select(int dst_idx) { Thunk* target = get_dst(dst_idx); Thunk* str = arg(2); Thunk* pos = arg(1); char* chars; if(str->desc == (Desc*) __STRING_PTR__) { chars = str->_string_ptr->chars; } else { chars = str->_array._chars; } target->desc = (Desc*) __CHAR__; target->_int = (char) chars[pos->_int]; } Thunk* string_create(Thunk* target, int len) { int newsize = sizeof (Desc) + sizeof (Array) + len; if(target == NULL) { target = (Thunk*) alloc_heap(newsize); } else if(target->desc->thunk_size < newsize) { Thunk* tmp = (Thunk*) alloc_heap(newsize); target->desc = (Desc*) __FORWARD_PTR__; target->_forward_ptr = tmp; target = tmp; } target->desc = (Desc*) __ARRAY__; target->_array.is_string = true; target->_array.is_boxed = true; target->_array.bytes_per_elem = 1; target->_array.length = len; return target; } void __string_create1(int dst_idx) { Thunk* target = get_dst(dst_idx); Thunk* len = arg(1); set_return(dst_idx, string_create(target, len->_int)); } void __string_create2(int dst_idx) { Thunk* target = get_dst(dst_idx); Thunk* len = arg(2); Thunk* ch = arg(1); target = string_create(target, len->_int); for(int i=0; i_int; i++) { target->_array._chars[i] = (char) ch->_int; } set_return(dst_idx, target); } void __string_update(int dst_idx) { Thunk* target = get_dst(dst_idx); Thunk* str = arg(3); Thunk* idx = arg(2); Thunk* ch = arg(1); int length; char* chars; if(str->desc == (Desc*) __STRING_PTR__) { chars = str->_string_ptr->chars; length = str->_string_ptr->length; } else { chars = str->_array._chars; length = str->_array.length; } target = string_create(target, length); memcpy(target->_array._chars, chars, length); target->_array._chars[idx->_int] = (char) ch->_int; set_return(dst_idx, target); } void __string_slice(int dst_idx) { Thunk* target = get_dst(dst_idx); Thunk* str = arg(3); Thunk* idx1 = arg(2); Thunk* idx2 = arg(1); char* chars; int full_length; if(str->desc == (Desc*) __STRING_PTR__) { chars = str->_string_ptr->chars; full_length = str->_string_ptr->length; } else { chars = str->_array._chars; full_length = str->_array.length; } int length = idx2->_int - idx1->_int + 1; if(idx1->_int + length > full_length) length = full_length - idx1->_int; target = string_create(target, length); memcpy(target->_array._chars, chars + idx1->_int, length); set_return(dst_idx, target); } void __string_append(int dst_idx) { Thunk* target = get_dst(dst_idx); Thunk* str1 = arg(2); Thunk* str2 = arg(1); int length1; char* chars1; if(str1->desc == (Desc*) __STRING_PTR__) { chars1 = str1->_string_ptr->chars; length1 = str1->_string_ptr->length; } else { chars1 = str1->_array._chars; length1 = str1->_array.length; } int length2; char* chars2; if(str2->desc == (Desc*) __STRING_PTR__) { chars2 = str2->_string_ptr->chars; length2 = str2->_string_ptr->length; } else { chars2 = str2->_array._chars; length2 = str2->_array.length; } target = string_create(target, length1 + length2); memcpy(target->_array._chars, chars1, length1); memcpy(target->_array._chars + length1, chars2, length2); set_return(dst_idx, target); } void __eqS(int dst_idx) { Thunk* target = get_dst(dst_idx); Thunk* str1 = arg(2); Thunk* str2 = arg(1); int length1; char* chars1; if(str1->desc == (Desc*) __STRING_PTR__) { chars1 = str1->_string_ptr->chars; length1 = str1->_string_ptr->length; } else { chars1 = str1->_array._chars; length1 = str1->_array.length; } int length2; char* chars2; if(str2->desc == (Desc*) __STRING_PTR__) { chars2 = str2->_string_ptr->chars; length2 = str2->_string_ptr->length; } else { chars2 = str2->_array._chars; length2 = str2->_array.length; } int eq = length1 == length2; int i = 0; while(idesc = (Desc*) __BOOL__; target->_int = eq; } void add_prim(int arity, int boxingMap, char* name, void (*exec)(int)) { int nameLength = strlen(name); // before the PrimEntry there are "arity" number of SliceEntries SliceEntry* entry_base = (SliceEntry*) alloc_desc(sizeof (SliceEntry) * arity + sizeof (PrimEntry) + nameLength + 1); PrimEntry* entry = (PrimEntry*) (entry_base + arity); entry->base.type = FT_PRIM; entry->base.arity = arity; entry->base.thunk_size = thunk_size_f(arity); entry->base.hnf = false; entry->boxingMap = boxingMap; entry->exec = exec; // TODO: should it be copied at all? memcpy(entry->name, name, nameLength); entry->name[nameLength] = '\0'; // generate slices. avoid function call if arity is zero if (arity > 0) gen_slices(entry_base, (Desc*) entry, arity); add_desc(entry->name, (Desc*) entry); } void init_prim() { add_prim(2, 0b011, "addI", &__addI); add_prim(2, 0b011, "subI", &__subI); add_prim(2, 0b011, "multI", &__multI); add_prim(2, 0b011, "divI", &__divI); add_prim(2, 0b011, "gtI", &__gtI); add_prim(2, 0b011, "geI", &__geI); add_prim(2, 0b011, "geC", &__geC); add_prim(2, 0b011, "ltI", &__ltI); add_prim(2, 0b011, "eqI", &__eqI); add_prim(2, 0b011, "neqI", &__neqI); add_prim(2, 0b011, "eqB", &__eqB); add_prim(2, 0b011, "eqC", &__eqC); add_prim(1, 0b001, "not", &__not); add_prim(2, 0b011, "and", &__and); add_prim(2, 0b011, "or", &__or); add_prim(2, 0b011, "mod", &__mod); add_prim(1, 0b001, "C2I", &__C2I); add_prim(1, 0b000, "string_size", &__string_size); add_prim(2, 0b010, "string_select", &__string_select); add_prim(1, 0b001, "string_create1", &__string_create1); add_prim(2, 0b011, "string_create2", &__string_create2); add_prim(3, 0b110, "string_update", &__string_update); add_prim(3, 0b110, "string_slice", &__string_slice); add_prim(2, 0b000, "string_append", &__string_append); add_prim(2, 0b000, "eqS", &__eqS); }