diff --git a/rewrite/neonucleus.h b/rewrite/neonucleus.h index 5a95407..94697ed 100644 --- a/rewrite/neonucleus.h +++ b/rewrite/neonucleus.h @@ -211,13 +211,13 @@ const char *nn_getComputerAddress(nn_Computer *computer); // Everything is limited by the architecture. void nn_setArchitecture(nn_Computer *computer, const nn_Architecture *arch); // Gets the current architecture. -nn_Architecture *nn_getArchitecture(nn_Computer *computer); +const nn_Architecture *nn_getArchitecture(nn_Computer *computer); // Sets the computer's desired architecture. // The desired architecture indicates, when the computer state is CHARCH, what the new architecture should be. // This is set even if it is not in the supported architecture list, *you must check if it is in that list first.* void nn_setDesiredArchitecture(nn_Computer *computer, const nn_Architecture *arch); // Gets the desired architecture. This is the architecture the computer should use after changing architectures. -nn_Architecture *nn_getDesiredArchitecture(nn_Computer *computer); +const nn_Architecture *nn_getDesiredArchitecture(nn_Computer *computer); // Adds a new supported architecture, which indicates to the code running on this computer that it is possible to switch to that architecture. void nn_addSupportedArchitecture(nn_Computer *computer, const nn_Architecture *arch); // Returns the array of supported architectures, as well as the length. @@ -293,6 +293,8 @@ typedef enum nn_ComponentAction { NN_COMP_DEINIT, // perform a method call NN_COMP_CALL, + // check if a method is enabled + NN_COMP_ENABLED, } nn_ComponentAction; typedef struct nn_ComponentRequest { @@ -303,11 +305,19 @@ typedef struct nn_ComponentRequest { // the local state of the component. NN_COMP_INIT should initialize this pointer. void *state; nn_Computer *computer; + // address of the component + const char *compAddress; + // the action requested nn_ComponentAction action; // for NN_COMP_CALL, it is the method called. + // for NN_COMP_ENABLED, it is the method being checked. const char *methodCalled; - // for NN_COMP_CALL, it is the amount of return values. - size_t returnCount; + union { + // for NN_COMP_CALL, it is the amount of return values. + size_t returnCount; + // for NN_COMP_ENABLED, it is whether the method is enabled. + bool methodEnabled; + }; } nn_ComponentRequest; typedef nn_Exit nn_ComponentHandler(nn_ComponentRequest *req); @@ -322,6 +332,10 @@ void nn_destroyComponentType(nn_ComponentType *ctype); nn_Exit nn_addComponent(nn_Computer *computer, nn_ComponentType *ctype, const char *address, size_t slot, void *userdata); // Checks if a component of that address exists. bool nn_hasComponent(nn_Computer *computer, const char *address); +// Checks if the component has that method. +// This not only checks if the method exists in the component type, +// but also checks if the method is enabled for the component instance. +bool nn_hasMethod(nn_Computer *computer, const char *address, const char *method); // removes a component. Outside of the initialization state (aka after the first tick), it also emits the signal for component removed. nn_Exit nn_removeComponent(nn_Computer *computer, const char *address); // Gets the name of a type of a component. diff --git a/rewrite/nn_include.c b/rewrite/nn_include.c new file mode 100644 index 0000000..b87ddee --- /dev/null +++ b/rewrite/nn_include.c @@ -0,0 +1,11 @@ +// Includes all the C files to compile the entire library in one Compilation Unit +// this is better than LTO, but it requires more RAM and compute. + +#include "nn_utils.h" + +#if defined(__STDC_NO_THREADS__) || defined(NN_WINDOWS) +#include "tinycthread.c" +#endif + +#include "nn_utils.c" +#include "nn_model.c" diff --git a/rewrite/nn_model.c b/rewrite/nn_model.c index 62cc5c9..07ae16e 100644 --- a/rewrite/nn_model.c +++ b/rewrite/nn_model.c @@ -12,5 +12,89 @@ nn_Universe *nn_createUniverse(nn_Context *ctx) { void nn_destroyUniverse(nn_Universe *universe) { nn_Context ctx = universe->ctx; + for(size_t i = 0; i < NN_BUILTIN_COUNT; i++) nn_destroyComponentType(universe->types[i]); nn_free(&ctx, universe, sizeof(nn_Universe)); } + +nn_ComponentType *nn_createComponentType(nn_Universe *universe, const char *name, void *userdata, const nn_ComponentMethod methods[], nn_ComponentHandler *handler) { + nn_Context *ctx = &universe->ctx; + char *namecpy = nn_strdup(ctx, name); + if(namecpy == NULL) return NULL; + + size_t methodCount = 0; + while(methods[methodCount].name != NULL) methodCount++; + // include the terminator! + methodCount++; + size_t methodSize = sizeof(nn_ComponentMethod) * methodCount; + + nn_ComponentMethod *methodscpy = nn_alloc(ctx, methodSize); + if(methodscpy == NULL) { + nn_strfree(ctx, namecpy); + return NULL; + } + + { + // in an ideal world, I'd just implement arenas. + // I should just implement arenas ngl + // TODO: just use arenas so memory management is ultra free + size_t methodIdx = 0; + while(methodIdx < methodCount) { + if(methods[methodIdx].name == NULL) { + methodscpy[methodIdx].name = NULL; + methodscpy[methodIdx].docString = NULL; + methodscpy[methodIdx].direct = false; + continue; + } + char *namecpy = nn_strdup(ctx, methods[methodIdx].name); + if(namecpy == NULL) goto methodOom; + char *doc = nn_strdup(ctx, methods[methodIdx].docString); + if(doc == NULL) { + nn_strfree(ctx, namecpy); + goto methodOom; + } + methodscpy[methodIdx].name = namecpy; + methodscpy[methodIdx].docString = doc; + methodscpy[methodIdx].direct = methods[methodIdx].direct; + methodIdx++; + } + goto normalExec; + methodOom: + for(size_t i = 0; i < methodIdx; i++) { + nn_strfree(ctx, (char *)methodscpy[i].name); + nn_strfree(ctx, (char *)methodscpy[i].docString); + } + return NULL; + } +normalExec:; + + nn_ComponentType *ctype = nn_alloc(ctx, sizeof(nn_ComponentType)); + if(ctype == NULL) { + nn_strfree(ctx, namecpy); + nn_free(ctx, methodscpy, methodSize); + return NULL; + } + + ctype->name = namecpy; + ctype->methods = methodscpy; + ctype->universe = universe; + return ctype; +} + +void nn_destroyComponentType(nn_ComponentType *ctype) { + nn_Context *ctx = &ctype->universe->ctx; + + nn_strfree(ctx, ctype->name); + + size_t methodCount = 0; + while(ctype->methods[methodCount].name != NULL) { + nn_strfree(ctx, (char *)ctype->methods[methodCount].name); + nn_strfree(ctx, (char *)ctype->methods[methodCount].docString); + methodCount++; + } + // include the terminator! + methodCount++; + size_t methodSize = sizeof(nn_ComponentMethod) * methodCount; + nn_free(ctx, ctype->methods, methodSize); + + nn_free(ctx, ctype, sizeof(nn_ComponentType)); +} diff --git a/rewrite/nn_model.h b/rewrite/nn_model.h index 708f676..f5533bb 100644 --- a/rewrite/nn_model.h +++ b/rewrite/nn_model.h @@ -13,6 +13,13 @@ typedef enum nn_BuiltinComponent { NN_BUILTIN_COUNT, } nn_BuiltinComponent; +typedef struct nn_ComponentType { + nn_Universe *universe; + char *name; + // NULL-terminated + nn_ComponentMethod *methods; +} nn_ComponentType; + typedef struct nn_Universe { nn_Context ctx; nn_ComponentType *types[NN_BUILTIN_COUNT]; @@ -20,6 +27,9 @@ typedef struct nn_Universe { typedef struct nn_Component { char *address; + nn_ComponentType *ctype; + size_t slot; + void *userdata; } nn_Component; // the values @@ -74,8 +84,10 @@ typedef struct nn_Computer { size_t totalMemory; double creationTimestamp; size_t stackSize; + size_t archCount; nn_Value callstack[NN_MAX_STACK]; char errorBuffer[NN_MAX_ERROR_SIZE]; + nn_Architecture archs[NN_MAX_ARCHITECTURES]; } nn_Computer; #endif diff --git a/rewrite/nn_utils.c b/rewrite/nn_utils.c index df89434..7f6f177 100644 --- a/rewrite/nn_utils.c +++ b/rewrite/nn_utils.c @@ -31,6 +31,37 @@ void nn_free(nn_Context *ctx, void *memory, size_t size) { ctx->alloc(ctx->state, memory, size, 0); } +size_t nn_strlen(const char *s) { + size_t l = 0; + while(*(s++) != '\0') l++; + return l; +} + +char *nn_strdup(nn_Context *ctx, const char *s) { + size_t l = nn_strlen(s); + char *buf = nn_alloc(ctx, sizeof(char) * (l+1)); + if(buf == NULL) return NULL; + nn_memcpy(buf, s, sizeof(char) * l); + buf[l] = '\0'; + return buf; +} + +void nn_strfree(nn_Context *ctx, char *s) { + size_t l = nn_strlen(s); + nn_free(ctx, s, sizeof(char) * (l+1)); +} + +void nn_memcpy(void *dest, const void *src, size_t len) { + char *out = (char *)dest; + const char *in = (const char *)src; + for(size_t i = 0; i < len; i++) out[i] = in[i]; +} + +void nn_memset(void *dest, int x, size_t len) { + char *out = (char *)dest; + for(size_t i = 0; i < len; i++) out[i] = (char)x; +} + nn_Lock *nn_createLock(nn_Context *ctx) { void *mem = nn_alloc(ctx, ctx->lockSize); if(mem == NULL) return NULL; diff --git a/rewrite/nn_utils.h b/rewrite/nn_utils.h index d75aea0..5d758bc 100644 --- a/rewrite/nn_utils.h +++ b/rewrite/nn_utils.h @@ -7,6 +7,13 @@ void *nn_alloc(nn_Context *ctx, size_t size); void *nn_realloc(nn_Context *ctx, void *memory, size_t oldSize, size_t newSize); void nn_free(nn_Context *ctx, void *memory, size_t size); +size_t nn_strlen(const char *s); +char *nn_strdup(nn_Context *ctx, const char *s); +void nn_strfree(nn_Context *ctx, char *s); + +void nn_memcpy(void *dest, const void *src, size_t len); +void nn_memset(void *dest, int x, size_t len); + typedef struct nn_Lock nn_Lock; nn_Lock *nn_createLock(nn_Context *ctx);