Last active
March 17, 2024 21:34
-
-
Save pervognsen/77c92814df2f2b1520a87c755ec71142 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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