Advertisement
BlueBear

nameless_interpreter.c

Feb 17th, 2017
243
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.02 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdint.h>
  4. #include <string.h>
  5. #include <assert.h>
  6.  
  7. /*
  8. Opcodes for the Nameless Language VM
  9. */
  10. enum Opcode
  11. {
  12.     OP_MOVR = 0,    //(0000)   Move the pointer to the right   
  13.     OP_MOVL = 1,    //(0001)   Move the pointer to the left
  14.     OP_INC = 2,     //(0010)   Increment the memory cell under the pointer
  15.     OP_DEC = 3,     //(0011)   Decrement the memory cell under the pointer
  16.     OP_POP = 4,     //(0100)   Output the character signified by the cell at the pointer
  17.     OP_PUSH = 5,    //(0101)   Input a character and store it in the cell at the pointer
  18.     OP_JEZ = 6,     //(0110)   Jump past the matching 0111 if the cell under the pointer is 0
  19.     OP_JNZ = 7,     //(0111)   Jump back to the matching 0110 if the cell under the pointer is nonzero
  20.     OP_ADD = 8,     //(1000)   Add the next command's base 10 equivalent to the current cell
  21.     OP_SUB = 9,     //(1001)   Subtract the next command's base 10 equivalent to the current cell
  22.     OP_NOP = 10,    //(1010)   No Operation
  23.     OP_CLC = 11,    //(1011)   Reset the current cell's value to 0
  24.     OP_CLPTR = 12   //(1100)   Reset the pointer to point at cell 0
  25. };
  26.  
  27. typedef struct VM
  28. {
  29.     unsigned int tapeSize;      //tape size in elements
  30.     unsigned int *program;      //program to run in VM
  31.     unsigned int programLength; //total program length
  32.     unsigned int SP;            //pointer to tape memory (stack pointer)
  33.     unsigned int PC;            //pointer to program memory
  34.     char *tape;                 //growable memory
  35. } VirtualMachine;
  36.  
  37. unsigned int ConvertBinaryStringToUInt(const char *bstring);
  38. size_t __cdecl strlen_ojeb(const char* text);
  39. void PrecompileSource(const char *source, unsigned int **program, unsigned int *programLength);
  40.  
  41. VirtualMachine *VM_Initialize(unsigned int *source, unsigned int programLength, unsigned int tapesize);
  42. void VM_Run(VirtualMachine *vm);
  43.  
  44. int main(void)
  45. {
  46.     /* hello world program [currently not working due to lack of the jump commands] */
  47.     const char *hello = "   00100010001000100010001000100010\
  48.                             0110\
  49.                             00000010001000100010\
  50.                             0110\
  51.                             000000100010\
  52.                             0000001000100010\
  53.                             0000001000100010\
  54.                             00000010\
  55.                             00010001000100010011\
  56.                             0111\
  57.                             00000010\
  58.                             00000010\
  59.                             00000011\
  60.                             000000000010\
  61.                             011000010111\
  62.                             00010011\
  63.                             0111\
  64.                             000000000100\
  65.                             00000011001100110100\
  66.                             0010001000100010001000100010010001000010001000100100\
  67.                             000000000100\
  68.                             000100110100\
  69.                             00010100\
  70.                             0010001000100100\
  71.                             0011001100110011001100110100\
  72.                             001100110011001100110011001100110100\
  73.                             0000000000100100";
  74.  
  75.     /* reads 5 chars from the input, and outputs them and increments them before outputting [works] */
  76.     const char *cat = "010100100000\
  77.                             010100100000\
  78.                             010100100000\
  79.                             010100100000\
  80.                             01010010\
  81.                             1100\
  82.                             01000000\
  83.                             01000000\
  84.                             01000000\
  85.                             01000000\
  86.                             01000000";
  87.  
  88.     /* reads and prints out one char [works] */
  89.     const char *pushpop = "010100100100";
  90.  
  91.     unsigned int *compiledProgram = NULL;
  92.     unsigned int programLength = 0;
  93.    
  94.     PrecompileSource(pushpop, &compiledProgram, &programLength);
  95.  
  96.     VirtualMachine *environment = NULL;
  97.     environment = VM_Initialize(compiledProgram, programLength, 100);
  98.     assert(environment != NULL);
  99.  
  100.     VM_Run(environment);
  101.    
  102.     getchar();
  103.     getchar();
  104.  
  105.  
  106.     return 0;
  107. }
  108.  
  109. /*
  110. @procedure(VM_Run)
  111.  
  112. This function is responsible for decoding the opcode and executing the operation over the Virtual Machine
  113. @param(vm): The Virtual Machine environment over which the Nameless program runs
  114. @param(opcode): The 4bit buffer containing one opcode
  115. */
  116. void VM_Run(VirtualMachine *vm)
  117. {
  118.     int loopcnt = 0;
  119.     while (vm->PC != vm->programLength)
  120.     {
  121.        
  122.         int op = vm->program[vm->PC];
  123.         switch (op)
  124.         {
  125.         case OP_MOVR: //(0000)   Move the pointer to the right
  126.         {
  127.             if (vm->SP == vm->tapeSize - 1)
  128.             {
  129.                 vm->SP = 0;
  130.             }
  131.             else
  132.             {
  133.                 vm->SP++;
  134.             }
  135.             break;
  136.         }
  137.         case OP_MOVL: //(0001)   Move the pointer to the left
  138.         {
  139.             if (vm->SP == 0)
  140.             {
  141.                 vm->SP = vm->tapeSize - 1;
  142.             }
  143.             else
  144.             {
  145.                 vm->SP--;
  146.             }
  147.             break;
  148.         }
  149.         case OP_INC: //(0010)   Increment the memory cell under the pointer
  150.         {
  151.             vm->tape[vm->SP]++;
  152.             break;
  153.         }
  154.         case OP_DEC: //(0011)   Decrement the memory cell under the pointer
  155.         {
  156.             vm->tape[vm->SP]--;
  157.             break;
  158.         }
  159.         case OP_POP: //(0100)   Output the character signified by the cell at the pointer
  160.         {
  161.             char c = vm->tape[vm->SP];
  162.             printf("%c", c);
  163.             break;
  164.         }
  165.         case OP_PUSH: //(0101)   Input a character and store it in the cell at the pointer
  166.         {
  167.             scanf(" %c", &vm->tape[vm->SP]);
  168.             break;
  169.         }
  170.         case OP_JEZ: //(0110)   Jump past the matching 0111 if the cell under the pointer is 0
  171.         {
  172.             break;
  173.         }
  174.         case OP_JNZ: //(0111)   Jump back to the matching 0110 if the cell under the pointer is nonzero
  175.         {
  176.             break;
  177.         }
  178.         case OP_ADD: //(1000)   Add the next command's base 10 equivalent to the current cell
  179.         {
  180.             vm->tape[vm->SP] += vm->program[vm->PC + 1];
  181.             break;
  182.         }
  183.         case OP_SUB: //(1001)   Subtract the next command's base 10 equivalent to the current cell
  184.         {
  185.             vm->tape[vm->SP] -= vm->program[vm->PC + 1];
  186.             break;
  187.         }
  188.         case OP_NOP: //(1010)   No Operation
  189.         {
  190.             //No Operation
  191.             break;
  192.         }
  193.         case OP_CLC: //(1011)   Reset the current cell's value to 0
  194.         {
  195.             vm->tape[vm->SP] = 0;
  196.             break;
  197.         }
  198.         case OP_CLPTR: //(1100)   Reset the pointer to point at cell 0
  199.         {
  200.             vm->SP = 0;
  201.             break;
  202.         }
  203.         }
  204.        
  205.         vm->PC++;
  206.     }
  207. }
  208.  
  209. /*
  210. @function(VM_Initialize)
  211.  
  212. Initializes the Virtual Machine with a program and creates a tape with [tapesize] number of cells
  213. @param(source): The Nameless Language program source
  214. @param(tapesize): The size of the tape memory to be created
  215. @return(vm): The pre-created and allocated virtual machine ready to use
  216. */
  217. VirtualMachine *VM_Initialize(unsigned int *source, unsigned int programLength, unsigned int tapesize)
  218. {
  219.     VirtualMachine *vm = (VirtualMachine *)malloc(sizeof(VirtualMachine));
  220.  
  221.     vm->tape = (char *)calloc(tapesize, sizeof(char));
  222.     vm->tapeSize = tapesize;
  223.     vm->program = source;
  224.     vm->programLength = programLength;
  225.     vm->SP = 0;
  226.     vm->PC = 0;
  227.  
  228.     return vm;
  229. }
  230.  
  231. /*
  232. @function(PrecompileSource)
  233.  
  234. "Precompiles" the source to base10 ordinal array (unsigned int []) and removes bad input and/or comments
  235. @param(source): The Nameless Language program source
  236. @param(program): The program to be precompiled
  237. @param(programLength): The precompiled program length
  238. */
  239. void PrecompileSource(const char *source, unsigned int **program, unsigned int *programLength)
  240. {
  241.     unsigned int compiled[10000];
  242.     register unsigned int len = strlen_ojeb(source);
  243.     register unsigned int srclen = 0;
  244.     char op[5];
  245.     op[4] = '\0';
  246.  
  247.     for (register int i = 0; i < len; i++)
  248.     {
  249.         if (source[i] == '0' || source[i] == '1')
  250.         {
  251.             register int cnt = srclen % 4;
  252.             op[cnt] = source[i];
  253.             srclen++;
  254.             if (cnt == 3)
  255.             {
  256.                 compiled[(*programLength)] = ConvertBinaryStringToUInt(op);
  257.                 (*programLength)++;
  258.             }
  259.         }
  260.     }
  261.     *program = compiled;
  262. }
  263.  
  264. /*
  265. @function(ConvertBinaryStringToUInt)
  266.  
  267. Converts the binary string into a decimal number
  268. @param(bstring): The binary number as string
  269. @return(total): The base10 value of the binary string
  270. */
  271. unsigned int ConvertBinaryStringToUInt(const char *bstring)
  272. {
  273.     const char* start = &bstring[0];
  274.     unsigned int total = 0;
  275.     while (*start)
  276.     {
  277.         total <<= 1;
  278.         if (*start++ == '1')
  279.         {
  280.             total ^= 1;
  281.         }
  282.     }
  283.     return total;
  284. }
  285.  
  286. /*
  287. @function(strlen_ojeb)
  288.  
  289. 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
  290. @param(text): The text which length we want to know
  291. @return(): The string length
  292. */
  293. size_t __cdecl strlen_ojeb(const char* text)
  294. {
  295.     const char *s;
  296.     const uint32_t* pdwText;
  297.     register uint32_t dwText;
  298.  
  299.     pdwText = (uint32_t*)text;
  300.     while (1)
  301.     {
  302.         dwText = *pdwText;
  303.  
  304.         if ((dwText - 0x01010101UL) & ~dwText & 0x80808080UL)
  305.         {
  306.             s = (const char*)pdwText;
  307.             while (*s)
  308.             {
  309.                 s++;
  310.             }
  311.             return s - text;
  312.         }
  313.         pdwText++;
  314.     }
  315. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement