aboutsummaryrefslogtreecommitdiffstats
path: root/prototypes/connections/module.h
diff options
context:
space:
mode:
Diffstat (limited to 'prototypes/connections/module.h')
-rw-r--r--prototypes/connections/module.h72
1 files changed, 72 insertions, 0 deletions
diff --git a/prototypes/connections/module.h b/prototypes/connections/module.h
new file mode 100644
index 0000000..ab2d6fc
--- /dev/null
+++ b/prototypes/connections/module.h
@@ -0,0 +1,72 @@
+#ifndef PURE_MODULE_H
+#define PURE_MODULE_H
+#include "result.h"
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/* Pure module format v1 (docs/design/008-module-format.md). A toolchain such
+ * as aup produces it; Pure verifies it completely before anything executes, so
+ * a loaded module cannot overflow the stack, branch backwards or name a
+ * missing state. Fixed capacity: no allocation in load, run or replace. */
+enum {
+ PURE_MODULE_STATES = 32, PURE_MODULE_INPUTS = 8, PURE_MODULE_VIEWS = 24,
+ PURE_MODULE_HANDLERS = 64, PURE_MODULE_CODE = 512, PURE_MODULE_STACK = 64,
+ PURE_MODULE_NAME = 32, PURE_MODULE_STRINGS = 32768, PURE_MODULE_HEADER = 32
+};
+
+typedef enum {
+ PURE_OP_CONST, PURE_OP_LOAD, PURE_OP_DT, PURE_OP_ADD, PURE_OP_SUB, PURE_OP_MUL,
+ PURE_OP_DIV, PURE_OP_NEG, PURE_OP_LT, PURE_OP_LE, PURE_OP_GT, PURE_OP_GE,
+ PURE_OP_EQ, PURE_OP_NE, PURE_OP_AND, PURE_OP_OR, PURE_OP_NOT, PURE_OP_MIN,
+ PURE_OP_MAX, PURE_OP_CLAMP, PURE_OP_STORE, PURE_OP_JZ, PURE_OP_JMP, PURE_OP_COUNT
+} PureOpcode;
+
+typedef enum { PURE_EDGE_DOWN, PURE_EDGE_UP } PureEdge;
+typedef enum {
+ PURE_FAULT_NONE, PURE_FAULT_DIVIDE, PURE_FAULT_NON_FINITE, PURE_FAULT_CLAMP
+} PureFault;
+
+typedef struct { double value; uint32_t arg; uint8_t op; } PureOp;
+typedef struct { uint32_t start, length; } PureBlock;
+typedef struct { uint32_t event; PureBlock code; } PureHandler;
+
+typedef struct {
+ uint16_t states, inputs, views, handlers;
+ uint32_t code_count;
+ char state_names[PURE_MODULE_STATES][PURE_MODULE_NAME];
+ char input_names[PURE_MODULE_INPUTS][PURE_MODULE_NAME];
+ char view_names[PURE_MODULE_VIEWS][PURE_MODULE_NAME];
+ char input_keys[PURE_MODULE_INPUTS][PURE_MODULE_NAME];
+ double initial[PURE_MODULE_STATES];
+ PureBlock view_code[PURE_MODULE_VIEWS];
+ PureHandler handler[PURE_MODULE_HANDLERS];
+ PureOp code[PURE_MODULE_CODE];
+} PureModule;
+
+/* Decode and verify. On failure out is unspecified and error names the rule. */
+PureResult pure_module_load(const void *bytes, size_t size, PureModule *out,
+ char *error, size_t error_size);
+/* Index of a name, or -1. */
+int pure_module_state(const PureModule *, const char *name);
+int pure_module_input(const PureModule *, const char *name);
+int pure_module_view(const PureModule *, const char *name);
+
+/* One app instance: state values of a module. Every event is atomic: on a
+ * fault the values are exactly those before the event. */
+typedef struct {
+ const PureModule *module;
+ double values[PURE_MODULE_STATES];
+ PureFault fault;
+ uint32_t fault_pc;
+ uint64_t ticks, events;
+} PureApp;
+
+void pure_app_start(PureApp *, const PureModule *);
+PureResult pure_app_frame(PureApp *);
+PureResult pure_app_input(PureApp *, uint32_t input, PureEdge);
+bool pure_app_view(const PureApp *, uint32_t view, double *out);
+/* Switch to another verified module. States keep their value by name; new
+ * states start at their initial value. The module must outlive the app. */
+void pure_app_replace(PureApp *, const PureModule *);
+#endif