diff --git a/calc.leg b/calc.leg index 5f20f8d..0bb8816 100644 --- a/calc.leg +++ b/calc.leg @@ -16,7 +16,7 @@ #include "object.c" -oop globals; +//oop globals; // this should stay out of object.c because it manipulates Symbol members defined in this file @@ -133,7 +133,7 @@ oop prim_exit(oop params) int main(int argc, char **argv) { - // globals = makeMap(); + globals = makeMap(); set(intern("exit"), Symbol, value, makeFunction(prim_exit)); // map_set(globals, intern("exit"), makeFunction(prim_exit)); diff --git a/object.c b/object.c index d21b2a1..aff6af8 100644 --- a/object.c +++ b/object.c @@ -49,6 +49,7 @@ struct Function { primitive_t primitive; }; +// usefull for map's elements struct Pair { oop key; oop value; @@ -171,7 +172,7 @@ int oopcmp(oop a, oop b) ssize_t map_search(oop map, oop key) { - assert(map); + assert(is(Map, map)); assert(key); ssize_t l = 0, r = get(map, Map, size) - 1; while (l <= r) { @@ -195,33 +196,49 @@ oop map_get(oop map, oop key) #define MAP_CHUNK_SIZE 8 +oop map_insert(oop map, oop key, oop value, size_t pos) +{ + assert(is(Map, map)); + assert(key); + assert(value); + printf("inserting in map, size:%zu, capacity:%zu\n", get(map, Map, size), get(map, Map, capacity)); + if (pos > get(map, Map, size)) { // don't need to check for pos < 0 because size_t is unsigned + fprintf(stderr, "\nTrying to insert in a map out of bound\n"); + assert(-1); + } + + // check capacity and expand if needed + if (get(map, Map, size) >= get(map, Map, capacity)) { + printf("expanding, size:%zu, capacity:%zu\n", get(map, Map, size), get(map, Map, capacity)); + size_t newCapacity = get(map, Map, capacity) + MAP_CHUNK_SIZE; + set(map, Map, elements, memcheck(realloc(get(map, Map, elements), sizeof(struct Pair) * newCapacity))); + set(map, Map, capacity, newCapacity); + printf("expanded, size:%zu, capacity:%zu\n", get(map, Map, size), get(map, Map, capacity)); + } + + // insert + printf("before memmove\n"); + memmove(get(map, Map, elements) + pos + 1, get(map, Map, elements) + pos, sizeof(struct Pair) * get(map, Map, size) - pos); + // Maybe this syntax is not very nice and I should access the Pair stuff differently? + // I mean modifying something on a line that begin with "get"... :/ + get(map, Map, elements)[pos].value = value; + get(map, Map, elements)[pos].key = key; + set(map, Map, size, ++get(map, Map, size)); + + return map; +} + oop map_set(oop map, oop key, oop value) { assert(is(Map, map)); - //assert(is(String, key)); + assert(key); assert(value); ssize_t pos = map_search(map, key); if (pos >= 0) { get(map, Map, elements)[pos].value = value; - // In your opinion, which is better in C - // - Writing "return map" here and then write the rest of the function's code flat - // - Or use this if / else statement (like here) because of the symmetry of the pb - // and the fact that we return the same stuff anyway } else { pos = -1 - pos; - // check capacity and expand if needed - if (get(map, Map, size) >= get(map, Map, capacity)) { - size_t newCapacity = get(map, Map, capacity) + MAP_CHUNK_SIZE; - set(map, Map, elements, memcheck(realloc(get(map, Map, elements), sizeof(struct Pair) * newCapacity))); - set(map, Map, capacity, newCapacity); - } - // insert - memmove(get(map, Map, elements) + pos + 1, get(map, Map, elements) + pos, sizeof(struct Pair) * get(map, Map, size) - pos); - // Maybe this syntax is not very nice and I should access the Pair stuff differently? - // I mean modifying something on a line that begin with "get"... :/ - get(map, Map, elements)[pos].value = value; - get(map, Map, elements)[pos].key = key; - set(map, Map, size, ++get(map, Map, size)); + map_insert(map, key, value, pos); } return map; } @@ -288,61 +305,17 @@ void println(oop ast) printf("\n"); } -#define SYMBOL_TABLE_CHUNK 1024 - -typedef struct table_t -{ - oop *array; - size_t size; - size_t capacity; -} table_t; - -#define TABLE_INITIALISER \ - { \ - NULL, 0, 0 \ - } // first call to table_insert() will initialise storage - -table_t table = TABLE_INITIALISER; // safe but not strictly needed on Unix because BSS segment is initialised to all zeroes - -ssize_t table_search(table_t *table, char *ident) -{ - assert(table); - assert(ident); - ssize_t l = 0, r = table->size - 1; - while (l <= r) { - ssize_t mid = (l + r) / 2; - int cmpres = strcmp(get(table->array[mid], Symbol, name), ident); - if (cmpres > 0) r = mid - 1; - else if (cmpres < 0) l = mid + 1; - else return mid; // non-negative result => element found at this index - } - return -1 - l; // negative result => 'not found', reflected around -1 instead of 0 to allow 'not found' at index 0 -} - -// ssize_t result because -1 means 'error' -ssize_t table_insert(table_t *table, oop object, size_t pos) -{ - assert(is(Symbol, object)); - if (pos > table->size) { // don't need to check for pos < 0 because size_t is unsigned - return -1; - } - - if (table->size >= table->capacity) { - table->array = memcheck(realloc(table->array, sizeof(oop) * (table->capacity + SYMBOL_TABLE_CHUNK))); - table->capacity += SYMBOL_TABLE_CHUNK; - } - - memmove(table->array + pos + 1, table->array + pos, sizeof(*table->array) * (table->size - pos)); - table->array[pos] = object; - return ++(table->size); -} +oop globals; oop intern(char *ident) { - ssize_t res = table_search(&table, ident); // < 0 => not found - if (res >= 0) return table.array[res]; - res = -1 - res; // 'un-negate' the result by reflecting it around X=-1 - oop new_symbol = makeSymbol(memcheck(strdup(ident))); - table_insert(&table, new_symbol, res); - return new_symbol; + oop symbol = makeSymbol(memcheck(strdup(ident))); + ssize_t pos = map_search(globals, symbol); + if (pos >= 0) { + return get(globals, Map, elements)[pos].key; // So it this case symbol will be garbage collected right? + } + pos = -1 - pos; // 'un-negate' the result by reflecting it around X=-1 + map_insert(globals, symbol, null, pos); + return symbol; } + \ No newline at end of file diff --git a/test2.txt b/test2.txt index c1276ac..7328b4b 100644 --- a/test2.txt +++ b/test2.txt @@ -55,11 +55,17 @@ myObj[42] exit - +"checkpoint 8" sys = {} + +"checkpoint 9" + sys.id = "i am sys obj" +"checkpoint 10" sys.bye = exit +"checkpoint 10" + sys.bye(1,2,3)