Refactor Universal Machine interpreter
This commit is contained in:
parent
9376de6140
commit
7d4c2b3113
5 changed files with 42 additions and 26 deletions
4
Makefile
4
Makefile
|
@ -4,5 +4,5 @@ CFLAGS = -Wall -Werror -pedantic -O3
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: um
|
all: um
|
||||||
|
|
||||||
um: um.c
|
um: src/um.c
|
||||||
$(CC) $< -o $@ $(CFLAGS)
|
$(CC) $^ -o $@ $(CFLAGS)
|
||||||
|
|
|
@ -6,8 +6,8 @@ Solutions to the [[http://www.boundvariable.org/task.shtml][2006 ICFP Programmin
|
||||||
|
|
||||||
** Universal Machine
|
** Universal Machine
|
||||||
|
|
||||||
The Universal Machine is implemented in [[um.c]]. Compile it with =make=
|
The Universal Machine is implemented in [[src/um.c]]. Compile it with
|
||||||
and run it on a UM program:
|
=make= and run it on a UM program:
|
||||||
|
|
||||||
#+begin_src sh
|
#+begin_src sh
|
||||||
./um sandmark.umz # benchmark
|
./um sandmark.umz # benchmark
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include "um.h"
|
||||||
#include "uthash.h"
|
#include "uthash.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -5,13 +6,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
struct array {
|
|
||||||
uint32_t id;
|
|
||||||
uint32_t *arr;
|
|
||||||
uint32_t size;
|
|
||||||
UT_hash_handle hh;
|
|
||||||
};
|
|
||||||
|
|
||||||
void allocate_array(struct array **arrays, uint32_t next_id, uint32_t size) {
|
void allocate_array(struct array **arrays, uint32_t next_id, uint32_t size) {
|
||||||
struct array *a;
|
struct array *a;
|
||||||
a = malloc(sizeof(struct array));
|
a = malloc(sizeof(struct array));
|
||||||
|
@ -35,22 +29,17 @@ void free_array(struct array **arrays, uint32_t id) {
|
||||||
free(a);
|
free(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
uint32_t *read_program(char *filename) {
|
||||||
if (argc < 2) {
|
|
||||||
fprintf(stderr, "Usage: %s <program>\n", argv[0]);
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct stat file_stat;
|
struct stat file_stat;
|
||||||
if (stat(argv[1], &file_stat) == -1) {
|
if (stat(filename, &file_stat) == -1) {
|
||||||
fprintf(stderr, "Could not stat file %s\n", argv[1]);
|
fprintf(stderr, "Could not stat file %s\n", filename);
|
||||||
return EXIT_FAILURE;
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *fp = fopen(argv[1], "rb");
|
FILE *fp = fopen(filename, "rb");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
fprintf(stderr, "Could not open file %s\n", argv[1]);
|
fprintf(stderr, "Could not open file %s\n", filename);
|
||||||
return EXIT_FAILURE;
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t *program = malloc(file_stat.st_size);
|
uint32_t *program = malloc(file_stat.st_size);
|
||||||
|
@ -69,6 +58,10 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
void run(uint32_t *program) {
|
||||||
uint32_t reg[8] = {0}; // registers
|
uint32_t reg[8] = {0}; // registers
|
||||||
struct array *arrays = NULL; // arrays of platters
|
struct array *arrays = NULL; // arrays of platters
|
||||||
uint32_t next_id = 1; // next free index available for a new array
|
uint32_t next_id = 1; // next free index available for a new array
|
||||||
|
@ -79,8 +72,6 @@ int main(int argc, char **argv) {
|
||||||
uint32_t c = program[pc] & 7;
|
uint32_t c = program[pc] & 7;
|
||||||
uint32_t b = (program[pc] >> 3) & 7;
|
uint32_t b = (program[pc] >> 3) & 7;
|
||||||
uint32_t a = (program[pc] >> 6) & 7;
|
uint32_t a = (program[pc] >> 6) & 7;
|
||||||
/* printf("\n%zu: %u (op=%u, a=%u, b=%u, c=%u)\n", pc, program[pc], opcode, a, b, c); */
|
|
||||||
/* printf("reg[a] = %u, reg[b] = %u, reg[c] = %u\n", reg[a], reg[b], reg[c]); */
|
|
||||||
pc++;
|
pc++;
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -111,7 +102,7 @@ int main(int argc, char **argv) {
|
||||||
reg[a] = (~reg[b]) | (~reg[c]);
|
reg[a] = (~reg[b]) | (~reg[c]);
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
return EXIT_SUCCESS;
|
return;
|
||||||
case 8:
|
case 8:
|
||||||
allocate_array(&arrays, next_id, reg[c]);
|
allocate_array(&arrays, next_id, reg[c]);
|
||||||
reg[b] = next_id;
|
reg[b] = next_id;
|
||||||
|
@ -144,6 +135,16 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
free(program);
|
free(program);
|
||||||
free(arrays);
|
free(arrays);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
if (argc < 2) {
|
||||||
|
fprintf(stderr, "Usage: %s <program>\n", argv[0]);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t *program = read_program(argv[1]);
|
||||||
|
run(program);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
15
src/um.h
Normal file
15
src/um.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#include "uthash.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct array {
|
||||||
|
uint32_t id;
|
||||||
|
uint32_t *arr;
|
||||||
|
uint32_t size;
|
||||||
|
UT_hash_handle hh;
|
||||||
|
};
|
||||||
|
|
||||||
|
void allocate_array(struct array **arrays, uint32_t next_id, uint32_t size);
|
||||||
|
struct array *get_array(struct array *arrays, uint32_t id);
|
||||||
|
void free_array(struct array **arrays, uint32_t id);
|
||||||
|
uint32_t *read_program(char *filename);
|
||||||
|
void run(uint32_t *program);
|
Loading…
Add table
Add a link
Reference in a new issue