/* +--------------------------------------------------------------------------+ ** | _ _ _ | ** | | \ | | (_) | ** | | \| | ___ _ __ _ | ** | | . ` |/ _ \| |/ _` | | ** | | |\ | (_) | | (_| | | ** | |_| \_|\___/| |\__,_| | ** | _/ | | ** | |__/ | ** +--------------------------------------------------------------------------+ ** | Copyright (c) 2022 Francesco Cozzuto | ** +--------------------------------------------------------------------------+ ** | This file is part of The Noja Interpreter. | ** | | ** | The Noja Interpreter is free software: you can redistribute it and/or | ** | modify it under the terms of the GNU General Public License as published | ** | by the Free Software Foundation, either version 3 of the License, or (at | ** | your option) any later version. | ** | | ** | The Noja Interpreter is distributed in the hope that it will be useful, | ** | but WITHOUT ANY WARRANTY; without even the implied warranty of | ** | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General | ** | Public License for more details. | ** | | ** | You should have received a copy of the GNU General Public License along | ** | with The Noja Interpreter. If not, see . | ** +--------------------------------------------------------------------------+ ** | WHAT IS THIS FILE? | ** | This file implements the "static map" object. The static map object | ** | behaves like a read-only "map". (Note that "implementing an object" means| ** | a very specific thing in this interpreter. If you didn't know, check the | ** | src/objects folder.) | ** | | ** | THE STATIC MAP OBJECT | ** | The statis map is a read-only collection of objects. You can see it as | ** | an interface for static arrays. You can define an array of | ** | `StaticMapSlot`s and then wrap it in this object. When the map is | ** | accessed, a lookup is performed into the array. Something to note is that| ** | the array is converted to noja objects lazily when they are accessed, | ** | which makes the start-up times lower than a general purpose map. | ** +--------------------------------------------------------------------------+ ** | NOTES: | ** | - Only strings can be keys. There is no intrinsic reason why | ** | it should be like that, it's just simpler. | ** +--------------------------------------------------------------------------+ */ #include #include #include "../runtime/runtime.h" #include "../utils/defs.h" #include "../objects/objects.h" typedef struct { Object base; Runtime *runt; const StaticMapSlot *slots; } StaticMapObject; static Object *select_(Object *self, Object *key, Heap *heap, Error *err); static Object *copy(Object *self, Heap *heap, Error *err); static int hash(Object *self); static TypeObject t_staticmap = { .base = (Object) { .type = &t_type, .flags = Object_STATIC }, .name = "static map", .size = sizeof (StaticMapObject), .copy = copy, .hash = hash, .select = select_, #warning "Need to walk the references" }; static Object *copy(Object *self, Heap *heap, Error *err) { (void) heap; (void) err; return self; } static int hash(Object *self) { (void) self; return 0; } Object *Object_NewStaticMap(StaticMapSlot slots[], void (*initfn)(StaticMapSlot[]), Runtime *runt, Error *error) { Heap *heap = Runtime_GetHeap(runt); // Make the thing. StaticMapObject *obj = (StaticMapObject*) Heap_Malloc(heap, &t_staticmap, error); { if(obj == 0) return 0; obj->runt = runt; obj->slots = slots; } if(initfn != NULL) initfn(slots); return (Object*) obj; } static Object *select_(Object *self, Object *key, Heap *heap, Error *error) { assert(self != NULL); assert(self->type == &t_staticmap); assert(key != NULL); assert(heap != NULL); assert(error != NULL); StaticMapObject *map = (StaticMapObject*) self; if(!Object_IsString(key)) return NULL; const char *name = Object_GetString(key, NULL); assert(name != NULL); if(map->slots == NULL) return NULL; for(int i = 0; map->slots[i].name != NULL; i += 1) if(!strcmp(name, map->slots[i].name)) { StaticMapSlot slot = map->slots[i]; Object *obj = NULL; switch(slot.kind) { case SM_BOOL: return Object_FromBool(slot.as_bool, heap, error); case SM_INT: return Object_FromInt(slot.as_int, heap, error); case SM_FLOAT: return Object_FromFloat(slot.as_float, heap, error); case SM_FUNCT: return Object_FromNativeFunction(map->runt, slot.as_funct, slot.argc, heap, error); case SM_STRING: return Object_FromString(slot.as_string, slot.length, heap, error); case SM_SMAP: return Object_NewStaticMap(slot.as_smap, NULL, map->runt, error); case SM_NONE: return Object_NewNone(heap, error); case SM_TYPE: return (Object*) slot.as_type; case SM_OBJECT: return slot.as_object; default: assert(0); break; } return obj; } return NULL; }