ec2-3-143-4-181.us-east-2.compute.amazonaws.com | ToothyWiki | ChrisHowlett | RecentChanges | Login | Webcomic
/*****************************************************************************/
/* ICFP UM implementation. This relies on ulongs being 32 bits. */
/*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
typedef unsigned long ulong;
typedef ulong platter;
platter reg[8];
typedef struct array
{
ulong size;
platter *platters;
} array;
array zero;
platter *finger;
#define ARRAY(index) ((index == 0) ? zero : (*((array *)index)))
int execute(void);
int main(int argc, char **argv)
{
/***************************************************************************/
/* Local variables. */
/***************************************************************************/
FILE *f;
struct stat stats;
ulong size;
ulong reading;
int ii;
unsigned char read_byte;
/***************************************************************************/
/* Initialise registers. */
/***************************************************************************/
memset(reg, 0, 8 * sizeof(platter));
/***************************************************************************/
/* Open the file. */
/***************************************************************************/
if (argc != 2)
{
printf("Usage: um file.um\n");
return 1;
}
if ((f = fopen(argv[1], "rb")) == NULL)
{
printf("Can't open input file for read\n");
return 2;
}
/***************************************************************************/
/* Check the file's size. */
/***************************************************************************/
fstat(fileno(f), &stats);
size = stats.st_size;
if (size % sizeof(platter) != 0)
{
printf("Bad file length\n");
return 3;
}
/***************************************************************************/
/* Allocate space in zero. */
/***************************************************************************/
zero.size = size / sizeof(platter);
zero.platters = malloc(zero.size * sizeof(platter));
/***************************************************************************/
/* Read file into zero. */
/***************************************************************************/
read_byte = fgetc(f);
finger = &(zero.platters[0]);
for (reading = 0; reading < zero.size; reading++)
{
*finger = 0;
for (ii = 0; ii < sizeof(platter); ii++)
{
*finger = (*finger << 8) + read_byte;
read_byte = fgetc(f);
}
finger++;
}
/***************************************************************************/
/* Set up finger. */
/***************************************************************************/
finger = &(zero.platters[0]);
/***************************************************************************/
/* Run it! */
/***************************************************************************/
return execute();
}
int execute(void)
{
/***************************************************************************/
/* Local variables. */
/***************************************************************************/
ulong comm;
unsigned char op,a,b,c;
array *temp_array;
int input;
/***************************************************************************/
/* Spin Cycle. */
/***************************************************************************/
while (1)
{
/*************************************************************************/
/* Read op, and advance finger. */
/*************************************************************************/
comm = *finger;
finger++;
op = (unsigned char)((comm & 0xF0000000) >> 28);
c = (unsigned char)(comm & 0x00000007);
b = (unsigned char)((comm >> 3) & 0x00000007);
a = (unsigned char)((comm >> 6) & 0x00000007);
/*************************************************************************/
/* Do op. */
/*************************************************************************/
switch (op)
{
case 0:
// Conditional Move
if (reg[c] != 0)
{
reg[a] = reg[b];
}
break;
case 1:
// Array Index
reg[a] = ARRAY(reg[b]).platters[reg[c]];
break;
case 2:
// Array Amendment
ARRAY(reg[a]).platters[reg[b]] = reg[c];
break;
case 3:
// Addition
reg[a] = reg[b] + reg[c];
break;
case 4:
// Multiplication
reg[a] = reg[b] * reg[c];
break;
case 5:
// Division
reg[a] = reg[b] / reg[c];
break;
case 6:
// Nand
reg[a] = ~(reg[b] & reg[c]);
break;
case 7:
// Halt
goto EXIT_LABEL;
break;
case 8:
// Allocation
temp_array = malloc(sizeof(array));
temp_array->size = reg[c];
temp_array->platters = malloc(reg[c] * sizeof(platter));
memset(temp_array->platters, 0, reg[c] * sizeof(platter));
reg[b] = (platter)temp_array;
break;
case 9:
// Abandonment
free(ARRAY(reg[c]).platters);
free((array *)reg[c]);
break;
case 10:
// Output
putchar((unsigned char)reg[c]);
break;
case 11:
// Input
input = getchar();
reg[c] = (input == EOF) ? 0xFFFFFFFF : input;
break;
case 12:
// Load
if (reg[b] == 0)
{
// Load zero
finger = &(zero.platters[reg[c]]);
}
else
{
// Load other
zero.platters = realloc(zero.platters, ARRAY(reg[b]).size * sizeof(platter));
zero.size = ARRAY(reg[b]).size;
memcpy(zero.platters,
ARRAY(reg[b]).platters,
zero.size * sizeof(platter));
finger = &(zero.platters[reg[c]]);
}
break;
case 13:
// Orthography
a = (unsigned char)((comm & 0x0E000000) >> 25);
reg[a] = comm & 0x01FFFFFF;
break;
default:
return 4;
}
}
EXIT_LABEL:
return 0;
}
Pity me, for I have written this:
,..|.................................................................................................................................,
:L v :
: *==================* *==================* :
: !send [(N,E),(N,S)]!->!send [(N,E),(N,S)]!----+ :
: *==================* *==================* | :
: | +-+ | :
: v | | :
: *==============* | *==================* | :
: !case N of S, E!-----#->!send [(Inl (), E)]!--#-------------------------------------------------------------------------------------
: *==============* | *==================* | :
: | | | :
: v | | :
: *=======* | | :
: !split N!---+ | | :
: *=======* | | +------------------+ :
: | | | | :
: v +--------#-----#--------------------------------------+ :
: *=======* | | | :
: !split N!---------+ | | | :
: *=======* | | +-#--------------------------------------#--------------------------------+ :
: | | | | | v v :
: v | | | | *=============================* *=====* *==================* *============* :
: *==============* | | | | +>!send [((W,(Inl(),Inl())), E)]!->!use L!->!send [(W,E),(W,S)]!->!send [(W,E)]!----------------------
: !case N of S, E!--#--#---+ | | *=============================* *=====* *==================* *============* :
: *==============* | | +--#--------------------------------+ | :
: | | +------+ +--------------------------+ | | :
: | +-------+ +--+ | +---#------------+ :
: | | v | | | :
: | *===================* | *=====* *==================*| | | :
---#->!send [(W,S), (W,E)]!-#>!use R!->!send [(W,E),(W,S)]!+ | | :
: | *===================* | *=====* *==================* | | *==================* :
: | | | | | +----------------------------------->!send [(W,E),(W,S)]!+ :
: | v v +-------#----+ *==================*| :
: | *=======* *=======* *=======* | | *==================* | | :
: +->!split N!----------+ !split N!->!split W!-#-------#--+ +>!send [(W,E),(W,S)]!------------------------#----------+ | :
: *=======* | *=======* *=======* | | | | *==================* | | | :
: | +---------#--+ | v +--#-+ | v | +-+ :
: +----+ v +-+ | *===========* | v *=============* *============*| | :
: | *===========* | +>!use multint!+ | *=========*+>!case W of S,E!->!send [(N,E)]!#-#---+ :
: |R(i) +>!use multint!+ | *===========*| | +>!use eqint!+ *=============* *============*| | v :
: | | *===========*| | v v | *=========* | | | *=====* :
: | | | | *===========* *===========* | *==================* v +-#-#>!use L!-----
: | +----------+ +-#-------------->!use plusint!->!use plusint!-#>!send [(W,S),(W,E)]!-+ *============* | | | *=====* :
: v | | *===========* *===========* | *==================* +->!send [(W,S)]! | | | :
:*==================*| | *=======* | | *============* | | | :
:!send [(N,E),(N,S)]!+ +>!split W!----------------------------------+ | +---+ | | | :
:*==================* *=======* | v | | | :
: | +----------------------------+ | *=========* *=============* | | | :
: | +------------#------->!use eqint!->!case W of E,S!-#-#-#-------------
: | | *=========* *=============* | | | :
: | | | | | | :
: | | +-------------------------#-------#-+ v :
: +-------------------------------------------+ | v | | *============*:
: | | *================* +-------#->!send [(N,S)]!:
: | +>!send [((W,N),S)]! | *============*:
: | *================* | | :
: | | +---+ | :
: | v | v :
: | *================* *==================*| *=====* :
: +---------------->!send [((W,N),E)]!->!send [(W,S),(W,E)]!+ +>!use L!---
: *================* *==================* | *=====* :
: +------+ :
,....................................................................................................................................,