plans
This commit is contained in:
12
TODO.md
12
TODO.md
@@ -5,6 +5,18 @@
|
||||
- userdata support
|
||||
- get rid of component signals (useless)
|
||||
|
||||
## Userdata system
|
||||
|
||||
The idea is that the computer stores userdata as structs which have a pointer (the state) and a bound-component address.
|
||||
When a component is removed, all of its associated userdata is instantly dropped.
|
||||
For serialization, the userdata pushes a string storing the encoded byte buffer.
|
||||
For deserialization, the userdata pops a string and decodes it.
|
||||
|
||||
To get component methods, requests are sent to get method info by index, and a NULL name means method is not allowed for that
|
||||
particular userdata. Methods can obviously be invoked just like component data.
|
||||
Serialization pushes the string on the stack, deserialization gets the buffer as ptr + len and sets the state pointer.
|
||||
They are handled by components, thus if it is not mounted at deserialization time, the deserialization fails.
|
||||
|
||||
# To re-evaluate
|
||||
|
||||
- Exposing the internal non-resizing hashmap implementation.
|
||||
|
||||
@@ -73,6 +73,9 @@ static nn_Exit luaArch_luaToNN(luaArch *arch, lua_State *L, int luaIdx) {
|
||||
if(lua_isboolean(L, luaIdx)) {
|
||||
return nn_pushbool(C, lua_toboolean(L, luaIdx));
|
||||
}
|
||||
if(lua_isuserdata(L, luaIdx)) {
|
||||
return nn_pushuserdata(C, (size_t)lua_touserdata(L, luaIdx));
|
||||
}
|
||||
luaL_error(L, "bad Lua value: %s", luaL_typename(L, luaIdx));
|
||||
return NN_EBADSTATE;
|
||||
}
|
||||
@@ -112,6 +115,10 @@ static void luaArch_nnToLua(luaArch *arch, lua_State *L, size_t nnIdx) {
|
||||
nn_popn(C, len * 2);
|
||||
return;
|
||||
}
|
||||
if(nn_isuserdata(C, nnIdx)) {
|
||||
lua_pushlightuserdata(L, (void *)nn_touserdata(C, nnIdx));
|
||||
return;
|
||||
}
|
||||
|
||||
luaL_error(L, "bad NN value: %s", nn_typenameof(C, nnIdx));
|
||||
}
|
||||
@@ -734,8 +741,11 @@ static nn_Exit luaArch_handler(nn_ArchitectureRequest *req) {
|
||||
return NN_OK;
|
||||
}
|
||||
return NN_OK;
|
||||
default:
|
||||
break;
|
||||
case NN_ARCH_SERIALIZE:
|
||||
return nn_pushstring(computer, "lua stuff");
|
||||
case NN_ARCH_DESERIALIZE:
|
||||
// do nothing
|
||||
return NN_OK;
|
||||
}
|
||||
return NN_OK;
|
||||
}
|
||||
|
||||
@@ -1645,7 +1645,7 @@ nn_Exit nn_deserializeComputer(nn_Computer *computer, const char *buf, size_t bu
|
||||
return computer->arch.handler(&req);
|
||||
}
|
||||
|
||||
nn_Exit nn_serializeComputer(nn_Computer *computer, char **buf, size_t *buflen) {
|
||||
nn_Exit nn_serializeComputer(nn_Computer *computer) {
|
||||
nn_ArchitectureRequest req;
|
||||
req.computer = computer;
|
||||
req.action = NN_ARCH_SERIALIZE;
|
||||
@@ -1655,24 +1655,9 @@ nn_Exit nn_serializeComputer(nn_Computer *computer, char **buf, size_t *buflen)
|
||||
nn_Exit e = computer->arch.handler(&req);
|
||||
if(e) return e;
|
||||
|
||||
*buf = req.memOut;
|
||||
*buflen = req.memLen;
|
||||
|
||||
return NN_OK;
|
||||
}
|
||||
|
||||
nn_Exit nn_freeSerializedComputer(nn_Computer *computer, char *buf, size_t buflen) {
|
||||
nn_ArchitectureRequest req;
|
||||
req.computer = computer;
|
||||
req.action = NN_ARCH_DROPSERIALIZED;
|
||||
req.globalState = computer->arch.state;
|
||||
req.localState = computer->archState;
|
||||
req.memOut = buf;
|
||||
req.memLen = buflen;
|
||||
|
||||
return computer->arch.handler(&req);
|
||||
}
|
||||
|
||||
void nn_setError(nn_Computer *computer, const char *s) {
|
||||
nn_setLError(computer, s, nn_strlen(s));
|
||||
}
|
||||
|
||||
@@ -350,12 +350,10 @@ typedef enum nn_ArchitectureAction {
|
||||
NN_ARCH_TICK,
|
||||
// get the free memory
|
||||
NN_ARCH_FREEMEM,
|
||||
// deserialize from an encoded state
|
||||
// deserialize from an encoded state, passed into request.
|
||||
NN_ARCH_DESERIALIZE,
|
||||
// serialize to an encoded state
|
||||
// serialize to an encoded state, pushed it as a string
|
||||
NN_ARCH_SERIALIZE,
|
||||
// drop the encoded buffer
|
||||
NN_ARCH_DROPSERIALIZED,
|
||||
} nn_ArchitectureAction;
|
||||
|
||||
typedef struct nn_ArchitectureRequest {
|
||||
@@ -373,12 +371,9 @@ typedef struct nn_ArchitectureRequest {
|
||||
bool synchronized;
|
||||
// in the case of NN_ARCH_FREEMEM, the free memory
|
||||
size_t freeMemory;
|
||||
// in the case of NN_ARCH_DESERIALIZE, NN_ARCH_SERIALIZE and NN_ARCH_DROPSERIALIZED, the buffer.
|
||||
// in the case of NN_ARCH_DESERIALIZE, the buffer.
|
||||
struct {
|
||||
union {
|
||||
char *memOut;
|
||||
const char *memIn;
|
||||
};
|
||||
const char *memIn;
|
||||
size_t memLen;
|
||||
};
|
||||
};
|
||||
@@ -540,14 +535,13 @@ double nn_getUptime(nn_Computer *computer);
|
||||
|
||||
// Deserialize an encoded computer state.
|
||||
// Encoding depends on architecture.
|
||||
// Will push it as a string and then call the architecture, which will decode it and pop it.
|
||||
nn_Exit nn_deserializeComputer(nn_Computer *computer, const char *buf, size_t buflen);
|
||||
|
||||
// Serialize the computer state.
|
||||
// Encoding depends on architecture.
|
||||
nn_Exit nn_serializeComputer(nn_Computer *computer, char **buf, size_t *buflen);
|
||||
|
||||
// Free the serialized buffer.
|
||||
nn_Exit nn_freeSerializedComputer(nn_Computer *computer, char *buf, size_t buflen);
|
||||
// Pushes the output, if successful, as a string on the stack.
|
||||
nn_Exit nn_serializeComputer(nn_Computer *computer);
|
||||
|
||||
// address is copied.
|
||||
// It can be NULL if you wish to have no tmp address.
|
||||
@@ -771,8 +765,8 @@ void nn_getComponents(nn_Computer *c, const char **components);
|
||||
// invoke the component method.
|
||||
// Everything on-stack is taken as an argument.
|
||||
// Will pop off trailing nulls.
|
||||
// Every remaining is what the component returned.
|
||||
// In the case of
|
||||
// Every remaining stack value is what the component returned.
|
||||
// In the case of errors, the contents of the stack is undefined
|
||||
nn_Exit nn_invokeComponent(nn_Computer *computer, const char *compAddress, const char *method);
|
||||
|
||||
// send a signal to a component.
|
||||
@@ -780,6 +774,40 @@ nn_Exit nn_invokeComponent(nn_Computer *computer, const char *compAddress, const
|
||||
// assumes one is specified.
|
||||
nn_Exit nn_signalComponent(nn_Component *component, nn_Computer *computer, const char *signal);
|
||||
|
||||
// Userdata!!!!
|
||||
|
||||
// Allocates a userdata index. Returns -1 on failure or if there are too many.
|
||||
int nn_allocUserdata(nn_Computer *computer, void *state, const char *compAddress);
|
||||
|
||||
// Frees a userdata index.
|
||||
void nn_freeUserdata(nn_Computer *computer, size_t userdata);
|
||||
|
||||
// Returns whether the userdata index is valid
|
||||
bool nn_isUserdataValid(nn_Computer *computer, size_t userdata);
|
||||
|
||||
// If compAddress is correct and userdata is valid, returns the state pointer.
|
||||
// If not, returns NULL, to prevent UB.
|
||||
void *nn_unwrapUserdata(nn_Computer *computer, size_t userdata, const char *compAddress);
|
||||
|
||||
// gets the component address which manages this userdata
|
||||
const char *nn_getUserdataComponent(nn_Computer *computer, size_t userdata);
|
||||
|
||||
// Gets information about a method of this userdata, by index.
|
||||
// If idx is out of bounds, this returns true, which means to stop iteration.
|
||||
// If method->name is NULL, the method should be skipped.
|
||||
bool nn_getUserdataMethod(nn_Computer *computer, size_t userdata, size_t idx, nn_Method *method);
|
||||
|
||||
// Invokes a method on some userdata, same semantics as nn_invokeComponent
|
||||
nn_Exit nn_invokeUserdata(nn_Computer *computer, size_t userdata, const char *method);
|
||||
|
||||
// Serializes the userdata into a buffer and pushes it as a string.
|
||||
// Make sure to keep track of its index and component address!
|
||||
nn_Exit nn_serializeUserdata(nn_Computer *computer, size_t userdata);
|
||||
|
||||
// Deserializes userdata at a particular index.
|
||||
// NOTE: if the component does not exist, or the userdata index is already taken, this errors.
|
||||
nn_Exit nn_deserializeUserdata(nn_Computer *computer, size_t userdata, const char *compAddress, const char *buf, size_t len);
|
||||
|
||||
// Sets the call budget.
|
||||
// The default is 1,000.
|
||||
void nn_setCallBudget(nn_Computer *computer, size_t budget);
|
||||
|
||||
Reference in New Issue
Block a user