From 06c6a099fd659f94a499183b306e0172eb4b3cdb Mon Sep 17 00:00:00 2001 From: IonutParau Date: Thu, 22 May 2025 18:12:27 +0200 Subject: [PATCH] lot of progress on computer --- src/component.c | 88 ++++++++++++++++++++++++++ src/component.h | 8 +-- src/computer.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++ src/computer.h | 4 ++ src/neonucleus.h | 6 +- src/universe.c | 1 + 6 files changed, 258 insertions(+), 6 deletions(-) diff --git a/src/component.c b/src/component.c index a6db3df..05f5f79 100644 --- a/src/component.c +++ b/src/component.c @@ -1,2 +1,90 @@ #include "neonucleus.h" +#include #include "component.h" + +nn_componentTable *nn_newComponentTable(const char *typeName, void *userdata, nn_componentConstructor *constructor, nn_componentDestructor *destructor) { + nn_componentTable *table = nn_malloc(sizeof(nn_componentTable)); + table->name = nn_strdup(typeName); + table->userdata = userdata; + table->constructor = constructor; + table->destructor = destructor; + table->methodCount = 0; + return table; +} + +void nn_destroyComponentTable(nn_componentTable *table) { + nn_free(table->name); + for(size_t i = 0; i < table->methodCount; i++) { + nn_method method = table->methods[i]; + nn_free(method.name); + nn_free(method.doc); + } + nn_free(table); +} + +void nn_defineMethod(nn_componentTable *table, const char *methodName, bool direct, nn_componentMethod *methodFunc, void *methodUserdata, const char *methodDoc) { + if(table->methodCount == NN_MAX_METHODS) return; + nn_method method; + method.method = methodFunc; + method.name = nn_strdup(methodName); + if(method.name == NULL) return; + method.direct = direct; + method.doc = nn_strdup(methodDoc); + if(method.doc == NULL) { + nn_free(method.name); + return; + } + method.userdata = methodUserdata; + table->methods[table->methodCount] = method; + table->methodCount++; +} + +const char *nn_getTableMethod(nn_componentTable *table, size_t idx, bool *outDirect) { + if(idx >= table->methodCount) return NULL; + nn_method method = table->methods[idx]; + if(outDirect != NULL) *outDirect = method.direct; + return method.name; +} + +const char *nn_methodDoc(nn_componentTable *table, const char *methodName) { + for(size_t i = 0; i < table->methodCount; i++) { + if(strcmp(table->methods[i].name, methodName) == 0) { + return table->methods[i].doc; + } + } + return NULL; +} + +nn_computer *nn_getComputerOfComponent(nn_component *component) { + return component->computer; +} + +nn_address nn_getComponentAddress(nn_component *component) { + return component->address; +} + +int nn_getComponentSlot(nn_component *component) { + return component->slot; +} + +nn_componentTable *nn_getComponentTable(nn_component *component) { + return component->table; +} + +void *nn_getComponentUserdata(nn_component *component) { + return component->statePtr; +} + +bool nn_invokeComponentMethod(nn_component *component, const char *name) { + nn_componentTable *table = component->table; + for(size_t i = 0; i < table->methodCount; i++) { + nn_method method = table->methods[i]; + if(strcmp(method.name, name) == 0) { + method.method(component->statePtr, method.userdata, component, component->computer); + return true; + } + } + + // no such method + return false; +} diff --git a/src/component.h b/src/component.h index b25a363..22f5ebb 100644 --- a/src/component.h +++ b/src/component.h @@ -5,18 +5,18 @@ #include "computer.h" typedef struct nn_method { - const char *name; + char *name; nn_componentMethod *method; void *userdata; - const char *doc; + char *doc; bool direct; } nn_method; typedef struct nn_componentTable { - const char *name; + char *name; void *userdata; nn_componentConstructor *constructor; - nn_componentConstructor *destructor; + nn_componentDestructor *destructor; nn_method methods[NN_MAX_METHODS]; size_t methodCount; } nn_componentTable; diff --git a/src/computer.c b/src/computer.c index 382adc9..fd39f71 100644 --- a/src/computer.c +++ b/src/computer.c @@ -1 +1,158 @@ #include "computer.h" +#include "component.h" +#include "neonucleus.h" +#include + +nn_computer *nn_newComputer(nn_universe *universe, nn_address address, nn_architecture *arch, void *userdata, size_t memoryLimit, size_t componentLimit); +void nn_tickComputer(nn_computer *computer); +double nn_getUptime(nn_computer *computer); +size_t nn_getComputerMemoryUsed(nn_computer *computer); +size_t nn_getComputerMemoryTotal(nn_computer *computer); +void *nn_getComputerUserData(nn_computer *computer); +void nn_addSupportedArchitecture(nn_computer *computer, nn_architecture *arch); +nn_architecture *nn_getArchitecture(nn_computer *computer); +nn_architecture *nn_getNextArchitecture(nn_computer *computer); +void nn_setNextArchitecture(nn_computer *computer, nn_architecture *arch); +void nn_deleteComputer(nn_computer *computer); +void nn_pushSignal(nn_computer *computer, nn_value *values, size_t len); +nn_value nn_fetchSignalValue(nn_computer *computer, size_t index); +void nn_popSignal(nn_computer *computer); +void nn_addUser(nn_computer *computer, const char *name); +void nn_deleteUser(nn_computer *computer, const char *name); +const char *nn_indexUser(nn_computer *computer, size_t idx); +bool nn_isUser(nn_computer *computer, const char *name); + +int nn_getState(nn_computer *computer) { + return computer->state; +} + +void nn_setState(nn_computer *computer, int state) { + computer->state = state; +} + +void nn_setEnergyInfo(nn_computer *computer, size_t energy, size_t capacity) { + computer->energy = energy; + computer->maxEnergy = capacity; +} + +size_t nn_getEnergy(nn_computer *computer) { + return computer->energy; +} + +void nn_removeEnergy(nn_computer *computer, size_t energy) { + if(computer->energy < energy) { + // blackout + computer->energy = 0; + computer->state = NN_STATE_BLACKOUT; + return; + } + computer->energy -= energy; +} + +void nn_addEnergy(nn_computer *computer, size_t amount) { + if(computer->maxEnergy - computer->energy < amount) { + computer->energy = computer->maxEnergy; + return; + } + computer->energy += amount; +} + +const char *nn_getError(nn_computer *computer) { + return computer->err; +} + +void nn_clearError(nn_computer *computer) { + if(computer->allocatedError) { + nn_free(computer->err); + } + computer->err = NULL; + computer->allocatedError = false; +} + +void nn_setError(nn_computer *computer, const char *err) { + nn_clearError(computer); + char *copy = nn_strdup(err); + if(copy == NULL) { + nn_setCError(computer, "out of memory"); + return; + } + computer->err = copy; + computer->allocatedError = true; +} + +void nn_setCError(nn_computer *computer, const char *err) { + nn_clearError(computer); + // we pinky promise this is safe + computer->err = (char *)err; + computer->allocatedError = false; +} + +nn_component *nn_newComponent(nn_computer *computer, nn_address address, int slot, nn_componentTable *table, void *userdata); + +void nn_removeComponent(nn_computer *computer, nn_address address) { + for(size_t i = 0; i < computer->componentLen; i++) { + if(strcmp(computer->components[i].address, address) == 0) { + nn_destroyComponent(computer->components + i); + } + } +} + +void nn_destroyComponent(nn_component *component) { + nn_free(component->address); + if(component->table->destructor != NULL) { + component->table->destructor(component->table->userdata, component->statePtr); + } + component->address = NULL; // marks component as freed +} + +nn_component *nn_findComponent(nn_computer *computer, nn_address address) { + for(size_t i = 0; i < computer->componentLen; i++) { + if(strcmp(computer->components[i].address, address) == 0) { + return computer->components + i; + } + } + return NULL; +} + +void nn_resetCall(nn_computer *computer) { + for(size_t i = 0; i < computer->argc; i++) { + nn_values_drop(computer->args[i]); + } + + for(size_t i = 0; i < computer->retc; i++) { + nn_values_drop(computer->rets[i]); + } + + computer->argc = 0; + computer->retc = 0; +} + +void nn_addArgument(nn_computer *computer, nn_value arg) { + if(computer->argc == NN_MAX_ARGS) return; + computer->args[computer->argc] = arg; + computer->argc++; +} + +void nn_return(nn_computer *computer, nn_value val) { + if(computer->retc == NN_MAX_RETS) return; + computer->rets[computer->retc] = val; + computer->retc++; +} + +nn_value nn_getArgument(nn_computer *computer, size_t idx) { + if(idx >= computer->argc) return nn_values_nil(); + return computer->args[idx]; +} + +nn_value nn_getReturn(nn_computer *computer, size_t idx) { + if(idx >= computer->retc) return nn_values_nil(); + return computer->rets[idx]; +} + +size_t nn_getArgumentCount(nn_computer *computer) { + return computer->argc; +} + +size_t nn_getReturnCount(nn_computer *computer) { + return computer->retc; +} diff --git a/src/computer.h b/src/computer.h index 97f2abb..2405097 100644 --- a/src/computer.h +++ b/src/computer.h @@ -5,6 +5,8 @@ typedef struct nn_computer { char state; + bool allocatedError; + char *err; nn_guard *lock; nn_component *components; size_t componentLen; @@ -21,6 +23,8 @@ typedef struct nn_computer { nn_universe *universe; char *users[NN_MAX_USERS]; size_t userCount; + size_t energy; + size_t maxEnergy; } nn_computer; #endif diff --git a/src/neonucleus.h b/src/neonucleus.h index 5160b2e..0fa6c50 100644 --- a/src/neonucleus.h +++ b/src/neonucleus.h @@ -72,7 +72,7 @@ typedef struct nn_architecture { char *(*serialize)(nn_computer *computer, void *state, void *userdata); void (*deserialize)(nn_computer *computer, const char *data, void *state, void *userdata); } nn_architecture; -typedef const char *nn_address; +typedef char *nn_address; // Values for architectures @@ -223,6 +223,7 @@ void nn_setCError(nn_computer *computer, const char *err); nn_component *nn_newComponent(nn_computer *computer, nn_address address, int slot, nn_componentTable *table, void *userdata); void nn_removeComponent(nn_computer *computer, nn_address address); +void nn_destroyComponent(nn_component *component); nn_computer *nn_getComputerOfComponent(nn_component *component); nn_address nn_getComponentAddress(nn_component *component); int nn_getComponentSlot(nn_component *component); @@ -244,7 +245,8 @@ const char *nn_methodDoc(nn_componentTable *table, const char *methodName); // Component calling -void nn_invokeComponentMethod(nn_component *component, const char *name); +/* Returns false if the method does not exist */ +bool nn_invokeComponentMethod(nn_component *component, const char *name); void nn_resetCall(nn_computer *computer); void nn_addArgument(nn_computer *computer, nn_value arg); void nn_return(nn_computer *computer, nn_value val); diff --git a/src/universe.c b/src/universe.c index 17d91fd..12384de 100644 --- a/src/universe.c +++ b/src/universe.c @@ -16,6 +16,7 @@ void nn_unsafeDeleteUniverse(nn_universe *universe) { for(size_t i = 0; i < universe->udataLen; i++) { nn_free(universe->udata[i].name); } + nn_free(universe); } void *nn_queryUserdata(nn_universe *universe, const char *name) {