Skip to content

Instantly share code, notes, and snippets.

@pervognsen
Last active March 17, 2024 21:34
Show Gist options
  • Save pervognsen/77c92814df2f2b1520a87c755ec71142 to your computer and use it in GitHub Desktop.
Save pervognsen/77c92814df2f2b1520a87c755ec71142 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct ion_type_t ion_type_t;
typedef struct ion_value_t ion_value_t;
typedef struct ion_state_t ion_state_t;
typedef struct ion_instruction_t ion_instruction_t;
typedef void (*ion_operation_t)(ion_state_t *, ion_value_t, ion_value_t, ion_value_t *);
struct ion_type_t {
const char *name;
ion_operation_t operations[256];
};
struct ion_value_t {
const ion_type_t *type;
union {
int64_t int64;
int64_t *pint64;
};
};
enum {
ION_ADD,
ION_GETAT,
ION_SETAT,
ION_PRINT,
};
struct ion_instruction_t {
uint8_t operation;
uint8_t first;
uint8_t second;
uint8_t result;
};
struct ion_state_t {
ion_value_t *stack;
ion_instruction_t *instruction;
};
void ion_error(ion_state_t *state, const char *error) {
printf("ion error: %s\n", error);
exit(1);
}
void ion_step(ion_state_t *state) {
ion_instruction_t *instruction = state->instruction++;
ion_value_t first = state->stack[instruction->first];
ion_value_t second = state->stack[instruction->second];
ion_value_t *result = state->stack + instruction->result;
first.type->operations[instruction->operation](state, first, second, result);
}
void ion_invalid_operation(ion_state_t *state, ion_value_t first, ion_value_t second, ion_value_t *result) {
ion_error(state, "invalid operation");
}
extern ion_type_t ion_builtin_types[];
enum {
ION_INT64,
ION_PINT64,
};
const ion_type_t *ion_type_int64 = &ion_builtin_types[ION_INT64];
const ion_type_t *ion_type_pint64 = &ion_builtin_types[ION_PINT64];
void int64_add(ion_state_t *state, ion_value_t first, ion_value_t second, ion_value_t *result) {
if (second.type != ion_type_int64) {
ion_error(state, "int64_add: invalid argument type");
}
result->type = ion_type_int64;
result->int64 = first.int64 + second.int64;
}
void int64_print(ion_state_t *state, ion_value_t first, ion_value_t second, ion_value_t *result) {
printf("(int64_t) %ld\n", first.int64);
}
void pint64_getat(ion_state_t *state, ion_value_t first, ion_value_t second, ion_value_t *result) {
result->type = ion_type_int64;
result->int64 = *first.pint64;
}
void pint64_setat(ion_state_t *state, ion_value_t first, ion_value_t second, ion_value_t *result) {
if (second.type != ion_type_int64) {
ion_error(state, "pint64_setat: invalid argument type");
}
*first.pint64 = second.int64;
}
void pint64_print(ion_state_t *state, ion_value_t first, ion_value_t second, ion_value_t *result) {
printf("(int64_t *) %p\n", first.pint64);
}
ion_type_t ion_builtin_types[] = {
[ION_INT64] = {
.name = "int64",
.operations = {
[ION_ADD] = int64_add,
[ION_PRINT] = int64_print,
}
},
[ION_PINT64] = {
.name = "pint64",
.operations = {
[ION_GETAT] = pint64_getat,
[ION_SETAT] = pint64_setat,
[ION_PRINT] = pint64_print,
}
},
};
void ion_initialize_builtin_types() {
for (size_t i = 0; i < sizeof(ion_builtin_types) / sizeof(*ion_builtin_types); i++) {
ion_type_t *type = &ion_builtin_types[i];
for (size_t operation = 0; operation < 256; operation++) {
if (!type->operations[operation]) {
type->operations[operation] = ion_invalid_operation;
}
}
}
}
int main() {
ion_initialize_builtin_types();
ion_instruction_t instructions[] = {
{ION_PRINT, 0}, // print r0
{ION_PRINT, 1}, // print r1
{ION_PRINT, 4}, // print r4
{ION_ADD, 0, 1, 2}, // r2 = r0 + r1
{ION_ADD, 1, 2, 3}, // r3 = r1 + r2
{ION_PRINT, 0}, // print r0
{ION_PRINT, 1}, // print r1
{ION_PRINT, 2}, // print r2
{ION_PRINT, 3}, // print r3
{ION_GETAT, 4, 0, 3}, // r3 = *r4
{ION_PRINT, 3}, // print r3
{ION_SETAT, 4, 2}, // *r4 = r2
{ION_GETAT, 4, 0, 3}, // r3 = *r4
{ION_PRINT, 3}, // print r3
};
int64_t some_value = 42;
ion_value_t stack[256] = {
[0] = {.type = ion_type_int64, .int64 = 1},
[1] = {.type = ion_type_int64, .int64 = 2},
[4] = {.type = ion_type_pint64, .pint64 = &some_value},
};
ion_state_t state = {.stack = stack, .instruction = instructions};
for (size_t i = 0; i < sizeof(instructions) / sizeof(*instructions); i++) {
ion_step(&state);
}
printf("%ld\n", some_value);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment