Skip to content

Instantly share code, notes, and snippets.

@cdleary
Created April 4, 2010 08:30
Show Gist options
  • Save cdleary/355236 to your computer and use it in GitHub Desktop.
Save cdleary/355236 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define STACK_SIZE 1024
#ifdef DEBUG
# define ASSERT(__condition) do { \
if (!(__condition)) { \
printf("Assertion failure: " #__condition); \
abort(); \
} \
} while (false)
#else
# define ASSERT(__condition)
#endif
typedef union {
enum BytecodeValues {
LOAD_IMM = 0,
ADD = 1,
SUB = 2,
MUL = 3,
PRINT = 4,
POP = 5,
SWAP = 6,
STOP = 7,
} name;
struct {
unsigned precise : 3;
} bitflag;
int value;
} Bytecode;
#define PRECISE(__bytecode) ((__bytecode).bitflag.precise)
Bytecode program[] = {LOAD_IMM, (Bytecode) 6, LOAD_IMM, (Bytecode) 5, LOAD_IMM, (Bytecode) 4,
SUB, SUB, PRINT, STOP};
static int stack[STACK_SIZE];
static int vpc = 0;
static int sp = 0; /* Limit index (no value at it). */
int
Interpret() {
#define DISPATCH do { \
switch (PRECISE(program[vpc++])) { \
case LOAD_IMM: goto load_imm; \
case ADD: goto add; \
case SUB: goto sub; \
case MUL: goto mul; \
case PRINT: goto print; \
case POP: goto pop; \
case SWAP: goto swap; \
case STOP: goto stop; \
default: goto bad_opcode; \
} \
} while (false)
int retcode;
switch (PRECISE(program[vpc++])) {
load_imm:
case LOAD_IMM:
stack[sp] = program[vpc++].value;
sp += 1;
DISPATCH;
add:
case ADD:
ASSERT(sp > 1);
stack[sp - 2] = stack[sp - 2] + stack[sp - 1];
sp -= 1;
DISPATCH;
sub:
case SUB:
ASSERT(sp > 1);
stack[sp - 2] = stack[sp - 2] - stack[sp - 1];
sp -= 1;
DISPATCH;
mul:
case MUL:
ASSERT(sp > 1);
stack[sp - 2] = stack[sp - 2] * stack[sp - 1];
sp -= 1;
DISPATCH;
print:
case PRINT:
ASSERT(sp > 0);
printf("%d\n", stack[sp - 1]);
sp -= 1;
DISPATCH;
pop:
case POP:
ASSERT(sp > 0);
sp--;
DISPATCH;
swap:
case SWAP:
{
ASSERT(sp > 1);
int tmp = stack[sp - 2];
stack[sp - 2] = stack[sp - 1];
stack[sp - 1] = tmp;
DISPATCH;
}
stop:
case STOP:
retcode = (sp > 0) ? EXIT_FAILURE : EXIT_SUCCESS;
break;
bad_opcode:
default:
retcode = EXIT_FAILURE;
}
printf("Done: %d\n", retcode);
return retcode;
#undef DISPATCH
}
#ifdef EXECUTABLE
int
main(int argc, char **argv) {
return Interpret();
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment