RNA/rna.c

From Esolang
Jump to: navigation, search
//
//  main.c
//  RNA
//
//  Created by Cyrus Hackford on 2011.
//  Copyright 2011 SI devIk. All rights reserved.
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define RNA_INTERP_VERSION "1.0"
#define RNA_STR_INIT_SIZE 32

#ifndef OBJC_BOOL_DEFINED
#define OBJC_BOOL_DEFINED
typedef signed char BOOL;
#define NO ((BOOL)0)
#define YES ((BOOL)1)
#endif


typedef struct _Memory {
	unsigned char *mem;
	unsigned long alloc;
	unsigned long used;
} Memory;

static BOOL appendMem(Memory *memory, const char *appendable) {
	size_t leng=strlen(appendable);
	
	if((memory->alloc-memory->used)<leng) {
		unsigned char *test=(unsigned char *)realloc(memory->mem, (size_t)(memory->used+leng+1));
		if(test==NULL)
			return NO;
		memory->mem=test;
		memory->alloc+=leng;
	}
	
	{
		unsigned char *temp=memory->mem;
		size_t length=leng;
		
		while(*temp!='\0')
			temp++;
		
		while(length!=0 && (*temp=*appendable++)!='\0') {
			length--;
			temp++;
		}
		
		if(*temp!='\0')
			*temp='\0';
	}
	
	memory->used+=leng;
	
	return YES;
}

static BOOL createMem(Memory **memory) {
	*memory=(Memory *)malloc(sizeof(Memory));
	if(*memory==NULL)
		return NO;
	
	(*memory)->mem=(unsigned char *)malloc(RNA_STR_INIT_SIZE+1);
	if((*memory)->mem==NULL) {
		free(*memory);
		
		return NO;
	}
	
	memset((*memory)->mem, 0, RNA_STR_INIT_SIZE+1);
	
	(*memory)->alloc=RNA_STR_INIT_SIZE;
	(*memory)->used=0;
	
	return YES;
}

static void destroyMem(Memory **memory, BOOL completely) {
	if(completely==YES)
		free((*memory)->mem);
	free(*memory);
}

static void dumpMem(Memory *memory, unsigned long limit) { // debugging purpose
	unsigned long loop=0, loopy;
	
	if(limit==0)
		loop=memory->alloc;
	else
		loop=limit<memory->alloc?limit:memory->alloc;
	
	printf("\nMemory#%lu: [", (unsigned long)memory);
	for(loopy=0; loopy<loop; ++loopy) {
		printf("%u", memory->mem[loopy]);
		
		if(loopy!=(loop-1))
			printf(", ");
	}
	printf("]\n");
}

static BOOL expandMem(Memory *memory, size_t size) {
	unsigned char *test;
	
	if(memory->alloc>=size)
		return YES;
	
	test=(unsigned char *)realloc(memory->mem, size+1);
	if(test==NULL)
		return NO;
	memory->mem=test;
	
	return YES;
}


static size_t ustrlen(const unsigned char *s) {
	const unsigned char *p=s;
	
	while(*p!='\0')
		p++;
	
	return (size_t)(p-s);
}

int main(int argc, const char **argv) {
	unsigned char *instructions;
	
	if(argc==1) {
		printf("The RNA Programming Language -- Interpreter v%s\nUsage: %s filename\n", RNA_INTERP_VERSION, argv[0]);
		
		return EXIT_FAILURE;
	}
	
	{
		BOOL failed;
		char *tempStrg;
		FILE *stream;
		Memory *instructionHolder;
		
		if(createMem(&instructionHolder)==NO) {
			printf("Interpreter error: Cannot allocate memory to hold RNA instructions.\nTerminated.\n");
			
			return EXIT_FAILURE;
		}
		
		if((stream=fopen(argv[1], "r"))==NULL) {
			printf("Interpreter error: Cannot open RNA instruction file: %s.\nTerminated.\n", argv[1]);
			destroyMem(&instructionHolder, YES);
			
			return EXIT_FAILURE;
		}
		
		failed=NO;
		if((tempStrg=(char *)malloc(sizeof(char)*512))==NULL) {
			printf("Interpreter error: Cannot allocate memory to hold RNA instructions.\nTerminated.\n");
			fclose(stream);
			destroyMem(&instructionHolder, YES);
			
			return EXIT_FAILURE;
		}
		
		while(feof(stream)==0) {
			fread(tempStrg, sizeof(char), 512, stream);
			if(appendMem(instructionHolder, tempStrg)==NO) {
				failed=YES;
				
				break;
			}
		}
		free(tempStrg);
		fclose(stream);
		
		if(failed==YES) {
			printf("Interpreter error: Cannot resize memory space used to hold RNA instructions.\nTerminated.\n");
			destroyMem(&instructionHolder, YES);
			
			return EXIT_FAILURE;
		}
		
		instructions=instructionHolder->mem;
		destroyMem(&instructionHolder, NO);
	}
	
	{
		// A=1 U=2 G=3 C=4
		unsigned char *ptr;
		Memory *memory;
		if(createMem(&memory)==NO) {
			printf("Interpreter error: Cannot allocate memory to hold on-execution data.\nTerminated.\n");
			free(instructions);
			
			return EXIT_FAILURE;
		}
		
		unsigned int codon=0, codonSize=100, loopActivatorIndex=0;
		unsigned long loop, loopActivators[2][64], loopy, strg;
		BOOL loopActivated=NO, skipUntilLoopTerminator=NO, started=NO;
		for(loop=ustrlen(instructions), loopy=0; loopy<loop; ++loopy) {
			{
				unsigned int inst=0;
				switch(instructions[loopy]) {
					case 'A':
					case 'a':
						inst=1;
						break;
					case 'U':
					case 'u':
						inst=2;
						break;
					case 'G':
					case 'g':
						inst=3;
						break;
					case 'C':
					case 'c':
						inst=4;
						break;
				}
				
				if(inst==0)
					continue;
				codon+=inst*codonSize;
			}
			
			if(codonSize==1) {
				if(started==NO) {
					if(codon==123) { // Metionine
						started=YES;
						strg=0;
						ptr=memory->mem;
					}
				} else {
					if(skipUntilLoopTerminator==YES && (codon==212 || codon==214))
						skipUntilLoopTerminator=NO;
					else {
						switch(codon) {
							case 211: // Termination
							case 213:
							case 231:
								started=NO;
								break;
							case 233: // Tryptophan
								strg=0;
								break;
							case 111: // Lysine
							case 113:
								++strg;
								break;
							case 112: // Asparagin
							case 114:
								--strg;
								break;
							case 341: // Alanine
							case 342:
							case 343:
							case 344:
								strg=(unsigned long)*ptr;
								break;
							case 141: // Threonine
							case 142:
							case 143:
							case 144:
								expandMem(memory, strg+1);
								ptr=&(memory->mem[strg]);
								break;
							case 441: // Proline
							case 442:
							case 443:
							case 444:
								{
									int temp;
									scanf("%d", &temp);
									*ptr=(unsigned char)(temp&0xF);
								}
								break;
							case 421: // Leucine
							case 422:
							case 423:
							case 424:
								printf("%c", (char)(*ptr&0x7F));
								break;
							case 131: // Arginine
							case 133:
							case 431:
							case 432:
							case 433:
							case 434:
								expandMem(memory, strg+1);
								*ptr+=memory->mem[strg];
								break;
							case 132: // Serine
							case 134:
							case 241:
							case 242:
							case 243:
							case 244:
								expandMem(memory, strg+1);
								*ptr*=memory->mem[strg];
								break;
							case 411: // Glutamine
							case 413:
								expandMem(memory, strg+1);
								*ptr-=memory->mem[strg];
								break;
							case 412: // Histidine
							case 414:
								expandMem(memory, strg+1);
								*ptr/=memory->mem[strg];
								break;
							case 311: // Glutamic acid
							case 313:
								expandMem(memory, strg+1);
								*ptr=(*ptr==memory->mem[strg]?1:0);
								break;
							case 312: // Aspartic acid
							case 314:
								if(*ptr==0) {
									if(loopActivated==NO)
										skipUntilLoopTerminator=YES;
									else {
										loopy=loopActivators[1][loopActivatorIndex--];
										loopActivated=NO;
									}
								} else {
									loopActivated=YES;
									loopActivators[0][loopActivatorIndex]=loopy-2;
								}
								break;
							case 212: // Tyrosine
							case 214:
								if(loopActivated==YES) {
									loopActivators[1][loopActivatorIndex]=codon+1;
									loopy=loopActivators[0][loopActivatorIndex--];
								}
								break;
							// Other codons are no-op yet. :)
						}
					}
				}
				
				codon=0;
				codonSize=100;
			} else
				codonSize/=10;
		}
	}
	
	free(instructions);
	
	return EXIT_SUCCESS;
}