Skip to content

Instantly share code, notes, and snippets.

@pervognsen
Last active October 23, 2022 11:00
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pervognsen/ed3525e14c3a9c11cb7d0e4ea7445b41 to your computer and use it in GitHub Desktop.
Save pervognsen/ed3525e14c3a9c11cb7d0e4ea7445b41 to your computer and use it in GitHub Desktop.
typedef enum {
CMD_INT = NODE_INT,
CMD_NEG = NODE_NEG,
CMD_NOT = NODE_NOT,
CMD_ADD = NODE_ADD,
CMD_SUB = NODE_SUB,
CMD_RET = 128,
CMD_SETREF,
CMD_GETREF,
} Cmd;
// Can ensure termination by requiring data stream to be capped with 5 RETs.
Node *load(const uint8_t *data) {
enum { MAX_STACK = 256 };
Node *stack[MAX_STACK];
Node *refs[256] = {0};
Node **tos = stack;
for (;;) {
Cmd cmd = *(uint8_t *)data++;
switch (cmd) {
case CMD_INT:
if (tos == stack + MAX_STACK) goto error;
*tos++ = int_node(*(int32_t *)data);
data += 4;
break;
case CMD_NEG:
case CMD_NOT:
if (tos <= stack) goto error;
tos[-1] = unary_node(cmd, tos[-1]);
break;
case CMD_ADD:
case CMD_SUB:
if (tos <= stack + 1) goto error;
tos[-2] = binary_node(cmd, tos[-2], tos[-1]);
tos--;
break;
case CMD_GETREF:
if (tos == stack + MAX_STACK) goto error;
*tos++ = refs[*(uint8_t *)data++];
break;
case CMD_SETREF:
if (tos <= stack) goto error;
refs[*(uint8_t *)data++] = *--tos;
break;
case CMD_RET:
if (tos != stack + 1) goto error;
return tos[-1];
default: error:
// clean up nodes
return 0;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment