|
|
@ -141,8 +141,8 @@ struct Map { |
|
|
|
struct Pair *elements; // even are keys, odd are values [ key val key val key val ] |
|
|
|
size_t capacity; |
|
|
|
union { |
|
|
|
size_t size; // free Maps will be reset to 0 size on allocation |
|
|
|
oop pool; // free list of Map objects |
|
|
|
size_t size; // free Maps will be reset to 0 size on allocation |
|
|
|
oop pool; // free list of Map objects |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
@ -197,7 +197,7 @@ oop _checkType(oop ptr, type_t type, char *file, int line) |
|
|
|
{ |
|
|
|
assert(ptr); |
|
|
|
if (getType(ptr) != type) { |
|
|
|
fprintf(stderr, "\n%s:%i: expected %i got %i\n", file, line, type, ptr->type); |
|
|
|
fprintf(stderr, "\n%s:%i: expected %i got %i\n", file, line, type, getType(ptr)); |
|
|
|
} |
|
|
|
assert(getType(ptr) == type); |
|
|
|
return ptr; |
|
|
@ -237,7 +237,7 @@ int isIntegerValue(int_t value) |
|
|
|
oop makeInteger(int_t value) |
|
|
|
{ |
|
|
|
#if (USE_TAG) |
|
|
|
if (isIntegerValue(value)) return (oop)(((intptr_t)value << 1) | 1); //TODO |
|
|
|
if (isIntegerValue(value)) return (oop)(((intptr_t)value << 1) | 1); |
|
|
|
#endif |
|
|
|
oop newInt = malloc(sizeof(struct Integer)); |
|
|
|
newInt->type = Integer; |
|
|
@ -267,11 +267,47 @@ oop makeString(char *value) |
|
|
|
return newString; |
|
|
|
} |
|
|
|
|
|
|
|
// value will be used directly |
|
|
|
oop makeStringFrom(char *value, size_t l) |
|
|
|
{ |
|
|
|
oop newString = malloc(sizeof(struct String)); |
|
|
|
newString->type = String; |
|
|
|
newString->String.value = value; |
|
|
|
newString->String.size = l; |
|
|
|
return newString; |
|
|
|
} |
|
|
|
|
|
|
|
oop makeStringFromChar(char c, int repeat) |
|
|
|
{ |
|
|
|
char *str= malloc(sizeof(char) * (repeat + 1)); |
|
|
|
for (int i=0; i<repeat; ++i) { |
|
|
|
str[i]= c; |
|
|
|
} |
|
|
|
str[repeat]= '\0'; |
|
|
|
return makeStringFrom(str, repeat); |
|
|
|
} |
|
|
|
|
|
|
|
size_t string_size(oop s) |
|
|
|
{ |
|
|
|
return get(s, String, size); |
|
|
|
} |
|
|
|
|
|
|
|
oop string_slice(oop str, ssize_t start, ssize_t stop) { |
|
|
|
assert(is(String, str)); |
|
|
|
size_t len = string_size(str); |
|
|
|
if (start < 0) start= start + len; |
|
|
|
if (stop < 0) stop= stop + len; |
|
|
|
if (start < 0 || start > len) return NULL; |
|
|
|
if (stop < 0 || stop > len) return NULL; |
|
|
|
if (start > stop) return NULL; |
|
|
|
|
|
|
|
size_t cpylen = stop - start; |
|
|
|
char *slice= memcheck(malloc(sizeof(char) * (cpylen + 1))); |
|
|
|
memcpy(slice, get(str, String, value) + start, cpylen); |
|
|
|
slice[cpylen]= '\0'; |
|
|
|
return makeStringFrom(slice, cpylen); |
|
|
|
} |
|
|
|
|
|
|
|
oop string_concat(oop str1, oop str2) |
|
|
|
{ |
|
|
|
size_t len = string_size(str1) + string_size(str2); |
|
|
@ -279,11 +315,7 @@ oop string_concat(oop str1, oop str2) |
|
|
|
memcpy(concat, get(str1, String, value), string_size(str1)); |
|
|
|
memcpy(concat + string_size(str1), get(str2, String, value), string_size(str2)); |
|
|
|
concat[len]= '\0'; |
|
|
|
oop newString = malloc(sizeof(struct String)); |
|
|
|
newString->type = String; |
|
|
|
newString->String.value = concat; |
|
|
|
newString->String.size = len; |
|
|
|
return newString; |
|
|
|
return makeStringFrom(concat, len); |
|
|
|
} |
|
|
|
|
|
|
|
oop string_mul(oop str, oop factor) |
|
|
@ -295,11 +327,7 @@ oop string_mul(oop str, oop factor) |
|
|
|
memcpy(concat + (i * string_size(str)), get(str, String, value), string_size(str)); |
|
|
|
} |
|
|
|
concat[len]= '\0'; |
|
|
|
oop newString = malloc(sizeof(struct String)); |
|
|
|
newString->type = String; |
|
|
|
newString->String.value = concat; |
|
|
|
newString->String.size = len; |
|
|
|
return newString; |
|
|
|
return makeStringFrom(concat, len); |
|
|
|
} |
|
|
|
|
|
|
|
oop makeSymbol(char *name) |
|
|
@ -311,6 +339,25 @@ oop makeSymbol(char *name) |
|
|
|
return newSymb; |
|
|
|
} |
|
|
|
|
|
|
|
oop makeSymbolFrom(char *name) |
|
|
|
{ |
|
|
|
oop newSymbol= malloc(sizeof(struct Symbol)); |
|
|
|
newSymbol->type= Symbol; |
|
|
|
newSymbol->Symbol.name= name; |
|
|
|
newSymbol->Symbol.prototype= 0; |
|
|
|
return newSymbol; |
|
|
|
} |
|
|
|
|
|
|
|
oop makeSymbolFromChar(char c, int repeat) |
|
|
|
{ |
|
|
|
char *str= malloc(sizeof(char) * (repeat + 1)); |
|
|
|
for (int i=0; i<repeat; ++i) { |
|
|
|
str[i]= c; |
|
|
|
} |
|
|
|
str[repeat]= '\0'; |
|
|
|
return makeSymbolFrom(str); |
|
|
|
} |
|
|
|
|
|
|
|
oop makeFunction(primitive_t primitive, oop name, oop param, oop body, oop parentScope, oop fixed) |
|
|
|
{ |
|
|
|
oop newFunc = malloc(sizeof(struct Function)); |
|
|
@ -326,11 +373,19 @@ oop makeFunction(primitive_t primitive, oop name, oop param, oop body, oop paren |
|
|
|
|
|
|
|
oop makeMap() |
|
|
|
{ |
|
|
|
oop newMap = malloc(sizeof(struct Map)); assert(0 == newMap->Map.flags); |
|
|
|
oop newMap = malloc(sizeof(struct Map)); assert(0 == newMap->Map.flags); |
|
|
|
newMap->type = Map; |
|
|
|
return newMap; |
|
|
|
} |
|
|
|
|
|
|
|
oop makeMapCapacity(size_t capa) |
|
|
|
{ |
|
|
|
oop map= makeMap(); |
|
|
|
set(map, Map, elements, malloc(sizeof(struct Pair) * capa)); |
|
|
|
set(map, Map, capacity, capa); |
|
|
|
return map; |
|
|
|
} |
|
|
|
|
|
|
|
size_t map_size(oop map) |
|
|
|
{ |
|
|
|
assert(is(Map, map)); |
|
|
@ -345,6 +400,14 @@ bool map_hasIntegerKey(oop map, size_t index) |
|
|
|
return index == getInteger(key); |
|
|
|
} |
|
|
|
|
|
|
|
bool map_isArray(oop map) |
|
|
|
{ |
|
|
|
assert(is(Map, map)); |
|
|
|
size_t size= map_size(map); |
|
|
|
if (size == 0) return true; |
|
|
|
return map_hasIntegerKey(map, 0) && map_hasIntegerKey(map, size-1); |
|
|
|
} |
|
|
|
|
|
|
|
int oopcmp(oop a, oop b) |
|
|
|
{ |
|
|
|
type_t ta = getType(a), tb = getType(b); |
|
|
@ -433,7 +496,7 @@ oop map_insert(oop map, oop key, oop value, size_t pos) |
|
|
|
// check capacity and expand if needed |
|
|
|
if (map_size(map) >= get(map, Map, capacity)) { |
|
|
|
size_t newCapacity = get(map, Map, capacity) * MAP_GROW_SIZE; |
|
|
|
if (newCapacity < MAP_MIN_SIZE) newCapacity= MAP_MIN_SIZE; |
|
|
|
if (newCapacity < MAP_MIN_SIZE) newCapacity= MAP_MIN_SIZE; |
|
|
|
set(map, Map, elements, realloc(get(map, Map, elements), sizeof(struct Pair) * newCapacity)); |
|
|
|
set(map, Map, capacity, newCapacity); |
|
|
|
} |
|
|
@ -482,6 +545,25 @@ oop map_append(oop map, oop value) |
|
|
|
return map_set(map, makeInteger(map_size(map)), value); |
|
|
|
} |
|
|
|
|
|
|
|
oop makeArrayFromElement(oop elem, int repeat) |
|
|
|
{ |
|
|
|
oop array= makeMapCapacity(repeat); |
|
|
|
for(int i=0; i < repeat; ++i) { |
|
|
|
map_append(array, elem); |
|
|
|
} |
|
|
|
return array; |
|
|
|
} |
|
|
|
|
|
|
|
oop makeArrayFromString(char *str) |
|
|
|
{ |
|
|
|
size_t len= strlen(str); |
|
|
|
oop array= makeMapCapacity(len); |
|
|
|
for(int i=0; i < len; ++i) { |
|
|
|
map_append(array, makeInteger(str[i])); |
|
|
|
} |
|
|
|
return array; |
|
|
|
} |
|
|
|
|
|
|
|
bool isHidden(oop obj) { |
|
|
|
if (is(Symbol, obj)) { |
|
|
|
char *s = get(obj, Symbol, name); |
|
|
@ -526,6 +608,36 @@ oop map_values(oop map) |
|
|
|
return values; |
|
|
|
} |
|
|
|
|
|
|
|
oop map_allValues(oop map) |
|
|
|
{ |
|
|
|
assert(is(Map, map)); |
|
|
|
oop values = makeMap(); |
|
|
|
for (size_t i = 0; i < get(map, Map, size); i++) { |
|
|
|
map_append(values, get(map, Map, elements)[i].value); |
|
|
|
} |
|
|
|
return values; |
|
|
|
} |
|
|
|
|
|
|
|
oop map_slice(oop map, ssize_t start, ssize_t stop) { |
|
|
|
assert(is(Map, map)); |
|
|
|
size_t len = map_size(map); |
|
|
|
if (start < 0) start= start + len; |
|
|
|
if (stop < 0) stop= stop + len; |
|
|
|
if (start < 0 || start > len) return NULL; |
|
|
|
if (stop < 0 || stop > len) return NULL; |
|
|
|
if (start > stop) return NULL; |
|
|
|
|
|
|
|
oop slice= makeMap(); |
|
|
|
if (start < stop) { |
|
|
|
if (!map_hasIntegerKey(map, start )) return NULL; |
|
|
|
if (!map_hasIntegerKey(map, stop - 1)) return NULL; |
|
|
|
for (size_t i= start; i < stop; ++i) { |
|
|
|
map_append(slice, get(map, Map, elements)[i].value); |
|
|
|
} |
|
|
|
} |
|
|
|
return slice; |
|
|
|
} |
|
|
|
|
|
|
|
DECLARE_BUFFER(oop, OopStack); |
|
|
|
OopStack printing = BUFFER_INITIALISER; |
|
|
|
|
|
|
|