plans
This commit is contained in:
12
TODO.md
12
TODO.md
@@ -5,6 +5,18 @@
|
|||||||
- userdata support
|
- userdata support
|
||||||
- get rid of component signals (useless)
|
- 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
|
# To re-evaluate
|
||||||
|
|
||||||
- Exposing the internal non-resizing hashmap implementation.
|
- 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)) {
|
if(lua_isboolean(L, luaIdx)) {
|
||||||
return nn_pushbool(C, lua_toboolean(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));
|
luaL_error(L, "bad Lua value: %s", luaL_typename(L, luaIdx));
|
||||||
return NN_EBADSTATE;
|
return NN_EBADSTATE;
|
||||||
}
|
}
|
||||||
@@ -112,6 +115,10 @@ static void luaArch_nnToLua(luaArch *arch, lua_State *L, size_t nnIdx) {
|
|||||||
nn_popn(C, len * 2);
|
nn_popn(C, len * 2);
|
||||||
return;
|
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));
|
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;
|
||||||
}
|
}
|
||||||
return NN_OK;
|
return NN_OK;
|
||||||
default:
|
case NN_ARCH_SERIALIZE:
|
||||||
break;
|
return nn_pushstring(computer, "lua stuff");
|
||||||
|
case NN_ARCH_DESERIALIZE:
|
||||||
|
// do nothing
|
||||||
|
return NN_OK;
|
||||||
}
|
}
|
||||||
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);
|
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;
|
nn_ArchitectureRequest req;
|
||||||
req.computer = computer;
|
req.computer = computer;
|
||||||
req.action = NN_ARCH_SERIALIZE;
|
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);
|
nn_Exit e = computer->arch.handler(&req);
|
||||||
if(e) return e;
|
if(e) return e;
|
||||||
|
|
||||||
*buf = req.memOut;
|
|
||||||
*buflen = req.memLen;
|
|
||||||
|
|
||||||
return NN_OK;
|
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) {
|
void nn_setError(nn_Computer *computer, const char *s) {
|
||||||
nn_setLError(computer, s, nn_strlen(s));
|
nn_setLError(computer, s, nn_strlen(s));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,12 +350,10 @@ typedef enum nn_ArchitectureAction {
|
|||||||
NN_ARCH_TICK,
|
NN_ARCH_TICK,
|
||||||
// get the free memory
|
// get the free memory
|
||||||
NN_ARCH_FREEMEM,
|
NN_ARCH_FREEMEM,
|
||||||
// deserialize from an encoded state
|
// deserialize from an encoded state, passed into request.
|
||||||
NN_ARCH_DESERIALIZE,
|
NN_ARCH_DESERIALIZE,
|
||||||
// serialize to an encoded state
|
// serialize to an encoded state, pushed it as a string
|
||||||
NN_ARCH_SERIALIZE,
|
NN_ARCH_SERIALIZE,
|
||||||
// drop the encoded buffer
|
|
||||||
NN_ARCH_DROPSERIALIZED,
|
|
||||||
} nn_ArchitectureAction;
|
} nn_ArchitectureAction;
|
||||||
|
|
||||||
typedef struct nn_ArchitectureRequest {
|
typedef struct nn_ArchitectureRequest {
|
||||||
@@ -373,12 +371,9 @@ typedef struct nn_ArchitectureRequest {
|
|||||||
bool synchronized;
|
bool synchronized;
|
||||||
// in the case of NN_ARCH_FREEMEM, the free memory
|
// in the case of NN_ARCH_FREEMEM, the free memory
|
||||||
size_t freeMemory;
|
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 {
|
struct {
|
||||||
union {
|
const char *memIn;
|
||||||
char *memOut;
|
|
||||||
const char *memIn;
|
|
||||||
};
|
|
||||||
size_t memLen;
|
size_t memLen;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -540,14 +535,13 @@ double nn_getUptime(nn_Computer *computer);
|
|||||||
|
|
||||||
// Deserialize an encoded computer state.
|
// Deserialize an encoded computer state.
|
||||||
// Encoding depends on architecture.
|
// 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);
|
nn_Exit nn_deserializeComputer(nn_Computer *computer, const char *buf, size_t buflen);
|
||||||
|
|
||||||
// Serialize the computer state.
|
// Serialize the computer state.
|
||||||
// Encoding depends on architecture.
|
// Encoding depends on architecture.
|
||||||
nn_Exit nn_serializeComputer(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);
|
||||||
// Free the serialized buffer.
|
|
||||||
nn_Exit nn_freeSerializedComputer(nn_Computer *computer, char *buf, size_t buflen);
|
|
||||||
|
|
||||||
// address is copied.
|
// address is copied.
|
||||||
// It can be NULL if you wish to have no tmp address.
|
// 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.
|
// invoke the component method.
|
||||||
// Everything on-stack is taken as an argument.
|
// Everything on-stack is taken as an argument.
|
||||||
// Will pop off trailing nulls.
|
// Will pop off trailing nulls.
|
||||||
// Every remaining is what the component returned.
|
// Every remaining stack value is what the component returned.
|
||||||
// In the case of
|
// 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);
|
nn_Exit nn_invokeComponent(nn_Computer *computer, const char *compAddress, const char *method);
|
||||||
|
|
||||||
// send a signal to a component.
|
// 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.
|
// assumes one is specified.
|
||||||
nn_Exit nn_signalComponent(nn_Component *component, nn_Computer *computer, const char *signal);
|
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.
|
// Sets the call budget.
|
||||||
// The default is 1,000.
|
// The default is 1,000.
|
||||||
void nn_setCallBudget(nn_Computer *computer, size_t budget);
|
void nn_setCallBudget(nn_Computer *computer, size_t budget);
|
||||||
|
|||||||
Reference in New Issue
Block a user