Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <string.h>
- #include <assert.h>
- /*
- Opcodes for the Nameless Language VM
- */
- enum Opcode
- {
- OP_MOVR = 0, //(0000) Move the pointer to the right
- OP_MOVL = 1, //(0001) Move the pointer to the left
- OP_INC = 2, //(0010) Increment the memory cell under the pointer
- OP_DEC = 3, //(0011) Decrement the memory cell under the pointer
- OP_POP = 4, //(0100) Output the character signified by the cell at the pointer
- OP_PUSH = 5, //(0101) Input a character and store it in the cell at the pointer
- OP_JEZ = 6, //(0110) Jump past the matching 0111 if the cell under the pointer is 0
- OP_JNZ = 7, //(0111) Jump back to the matching 0110 if the cell under the pointer is nonzero
- OP_ADD = 8, //(1000) Add the next command's base 10 equivalent to the current cell
- OP_SUB = 9, //(1001) Subtract the next command's base 10 equivalent to the current cell
- OP_NOP = 10, //(1010) No Operation
- OP_CLC = 11, //(1011) Reset the current cell's value to 0
- OP_CLPTR = 12 //(1100) Reset the pointer to point at cell 0
- };
- typedef struct VM
- {
- unsigned int tapeSize; //tape size in elements
- unsigned int *program; //program to run in VM
- unsigned int programLength; //total program length
- unsigned int SP; //pointer to tape memory (stack pointer)
- unsigned int PC; //pointer to program memory
- char *tape; //growable memory
- } VirtualMachine;
- unsigned int ConvertBinaryStringToUInt(const char *bstring);
- size_t __cdecl strlen_ojeb(const char* text);
- void PrecompileSource(const char *source, unsigned int **program, unsigned int *programLength);
- VirtualMachine *VM_Initialize(unsigned int *source, unsigned int programLength, unsigned int tapesize);
- void VM_Run(VirtualMachine *vm);
- int main(void)
- {
- /* hello world program [currently not working due to lack of the jump commands] */
- const char *hello = " 00100010001000100010001000100010\
- 0110\
- 00000010001000100010\
- 0110\
- 000000100010\
- 0000001000100010\
- 0000001000100010\
- 00000010\
- 00010001000100010011\
- 0111\
- 00000010\
- 00000010\
- 00000011\
- 000000000010\
- 011000010111\
- 00010011\
- 0111\
- 000000000100\
- 00000011001100110100\
- 0010001000100010001000100010010001000010001000100100\
- 000000000100\
- 000100110100\
- 00010100\
- 0010001000100100\
- 0011001100110011001100110100\
- 001100110011001100110011001100110100\
- 0000000000100100";
- /* reads 5 chars from the input, and outputs them and increments them before outputting [works] */
- const char *cat = "010100100000\
- 010100100000\
- 010100100000\
- 010100100000\
- 01010010\
- 1100\
- 01000000\
- 01000000\
- 01000000\
- 01000000\
- 01000000";
- /* reads and prints out one char [works] */
- const char *pushpop = "010100100100";
- unsigned int *compiledProgram = NULL;
- unsigned int programLength = 0;
- PrecompileSource(pushpop, &compiledProgram, &programLength);
- VirtualMachine *environment = NULL;
- environment = VM_Initialize(compiledProgram, programLength, 100);
- assert(environment != NULL);
- VM_Run(environment);
- getchar();
- getchar();
- return 0;
- }
- /*
- @procedure(VM_Run)
- This function is responsible for decoding the opcode and executing the operation over the Virtual Machine
- @param(vm): The Virtual Machine environment over which the Nameless program runs
- @param(opcode): The 4bit buffer containing one opcode
- */
- void VM_Run(VirtualMachine *vm)
- {
- int loopcnt = 0;
- while (vm->PC != vm->programLength)
- {
- int op = vm->program[vm->PC];
- switch (op)
- {
- case OP_MOVR: //(0000) Move the pointer to the right
- {
- if (vm->SP == vm->tapeSize - 1)
- {
- vm->SP = 0;
- }
- else
- {
- vm->SP++;
- }
- break;
- }
- case OP_MOVL: //(0001) Move the pointer to the left
- {
- if (vm->SP == 0)
- {
- vm->SP = vm->tapeSize - 1;
- }
- else
- {
- vm->SP--;
- }
- break;
- }
- case OP_INC: //(0010) Increment the memory cell under the pointer
- {
- vm->tape[vm->SP]++;
- break;
- }
- case OP_DEC: //(0011) Decrement the memory cell under the pointer
- {
- vm->tape[vm->SP]--;
- break;
- }
- case OP_POP: //(0100) Output the character signified by the cell at the pointer
- {
- char c = vm->tape[vm->SP];
- printf("%c", c);
- break;
- }
- case OP_PUSH: //(0101) Input a character and store it in the cell at the pointer
- {
- scanf(" %c", &vm->tape[vm->SP]);
- break;
- }
- case OP_JEZ: //(0110) Jump past the matching 0111 if the cell under the pointer is 0
- {
- break;
- }
- case OP_JNZ: //(0111) Jump back to the matching 0110 if the cell under the pointer is nonzero
- {
- break;
- }
- case OP_ADD: //(1000) Add the next command's base 10 equivalent to the current cell
- {
- vm->tape[vm->SP] += vm->program[vm->PC + 1];
- break;
- }
- case OP_SUB: //(1001) Subtract the next command's base 10 equivalent to the current cell
- {
- vm->tape[vm->SP] -= vm->program[vm->PC + 1];
- break;
- }
- case OP_NOP: //(1010) No Operation
- {
- //No Operation
- break;
- }
- case OP_CLC: //(1011) Reset the current cell's value to 0
- {
- vm->tape[vm->SP] = 0;
- break;
- }
- case OP_CLPTR: //(1100) Reset the pointer to point at cell 0
- {
- vm->SP = 0;
- break;
- }
- }
- vm->PC++;
- }
- }
- /*
- @function(VM_Initialize)
- Initializes the Virtual Machine with a program and creates a tape with [tapesize] number of cells
- @param(source): The Nameless Language program source
- @param(tapesize): The size of the tape memory to be created
- @return(vm): The pre-created and allocated virtual machine ready to use
- */
- VirtualMachine *VM_Initialize(unsigned int *source, unsigned int programLength, unsigned int tapesize)
- {
- VirtualMachine *vm = (VirtualMachine *)malloc(sizeof(VirtualMachine));
- vm->tape = (char *)calloc(tapesize, sizeof(char));
- vm->tapeSize = tapesize;
- vm->program = source;
- vm->programLength = programLength;
- vm->SP = 0;
- vm->PC = 0;
- return vm;
- }
- /*
- @function(PrecompileSource)
- "Precompiles" the source to base10 ordinal array (unsigned int []) and removes bad input and/or comments
- @param(source): The Nameless Language program source
- @param(program): The program to be precompiled
- @param(programLength): The precompiled program length
- */
- void PrecompileSource(const char *source, unsigned int **program, unsigned int *programLength)
- {
- unsigned int compiled[10000];
- register unsigned int len = strlen_ojeb(source);
- register unsigned int srclen = 0;
- char op[5];
- op[4] = '\0';
- for (register int i = 0; i < len; i++)
- {
- if (source[i] == '0' || source[i] == '1')
- {
- register int cnt = srclen % 4;
- op[cnt] = source[i];
- srclen++;
- if (cnt == 3)
- {
- compiled[(*programLength)] = ConvertBinaryStringToUInt(op);
- (*programLength)++;
- }
- }
- }
- *program = compiled;
- }
- /*
- @function(ConvertBinaryStringToUInt)
- Converts the binary string into a decimal number
- @param(bstring): The binary number as string
- @return(total): The base10 value of the binary string
- */
- unsigned int ConvertBinaryStringToUInt(const char *bstring)
- {
- const char* start = &bstring[0];
- unsigned int total = 0;
- while (*start)
- {
- total <<= 1;
- if (*start++ == '1')
- {
- total ^= 1;
- }
- }
- return total;
- }
- /*
- @function(strlen_ojeb)
- This string length function is here only because it is a bit faster code than in the standard library, feel free to use your own
- @param(text): The text which length we want to know
- @return(): The string length
- */
- size_t __cdecl strlen_ojeb(const char* text)
- {
- const char *s;
- const uint32_t* pdwText;
- register uint32_t dwText;
- pdwText = (uint32_t*)text;
- while (1)
- {
- dwText = *pdwText;
- if ((dwText - 0x01010101UL) & ~dwText & 0x80808080UL)
- {
- s = (const char*)pdwText;
- while (*s)
- {
- s++;
- }
- return s - text;
- }
- pdwText++;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement