1 module vm; 2 3 import std.stdio; 4 import std.string; 5 import std.regex; 6 import std.array; 7 import std.conv; 8 import core.stdc.stdio; 9 10 struct Instruction 11 { 12 void delegate(in size_t) dg; 13 size_t value; 14 } 15 16 class VirtualMachine 17 { 18 private: 19 size_t pcnt; 20 size_t ptr; 21 ubyte[] memory; 22 string source; 23 Instruction[] instructions; 24 25 void padd(in size_t n) 26 { 27 ptr += n; 28 } 29 void psub(in size_t n) 30 { 31 ptr -= n; 32 } 33 void dadd(in size_t n) 34 { 35 memory[ptr] += n; 36 } 37 void dsub(in size_t n) 38 { 39 memory[ptr] -= n; 40 } 41 void skip(in size_t n) 42 { 43 if(memory[ptr] == 0) pcnt = n; 44 } 45 void loop(in size_t n) 46 { 47 if(memory[ptr] != 0) pcnt = n; 48 } 49 void putc(in size_t n) 50 { 51 putchar(memory[ptr]); 52 } 53 void getc(in size_t n) 54 { 55 int tmp = getchar(); 56 if(tmp == EOF) throw new Error("EOF"); 57 memory[ptr] = tmp.to!ubyte; 58 } 59 void zero(in size_t n) 60 { 61 memory[ptr] = 0; 62 } 63 void end(in size_t n) 64 { 65 throw new Exception("end"); 66 } 67 public: 68 this(string _source, size_t buffsize) 69 { 70 memory = new ubyte[](buffsize); 71 source = _source; 72 } 73 void parse() 74 { 75 string formatted; 76 foreach(c;source) 77 { 78 if("+-<>[].,".indexOf(c) != -1) formatted ~= c; 79 } 80 formatted = formatted.replace(regex(r"\[-\]","g"),"z"); 81 size_t[] loopstack; 82 auto prev = ' '; 83 foreach(c;formatted) 84 { 85 switch(c) 86 { 87 case '>': 88 if(prev == '>') 89 { 90 instructions.back.value++; 91 }else{ 92 instructions ~= Instruction(&this.padd,1); 93 } 94 break; 95 case '<': 96 if(prev == '<') 97 { 98 instructions.back.value++; 99 }else{ 100 instructions ~= Instruction(&this.psub,1); 101 } 102 break; 103 case '+': 104 if(prev == '+') 105 { 106 instructions.back.value++; 107 }else{ 108 instructions ~= Instruction(&this.dadd,1); 109 } 110 break; 111 case '-': 112 if(prev == '-') 113 { 114 instructions.back.value++; 115 }else{ 116 instructions ~= Instruction(&this.dsub,1); 117 } 118 break; 119 case '[': 120 loopstack ~= instructions.length; 121 instructions ~= Instruction(&this.skip,0); 122 break; 123 case ']': 124 instructions[loopstack.back].value = instructions.length; 125 instructions ~= Instruction(&this.loop,loopstack.back); 126 loopstack.popBack(); 127 break; 128 case '.': 129 instructions ~= Instruction(&this.putc,0); 130 break; 131 case ',': 132 instructions ~= Instruction(&this.getc,0); 133 break; 134 case 'z': 135 instructions ~= Instruction(&this.zero,0); 136 break; 137 default: 138 } 139 prev = c; 140 } 141 instructions ~= Instruction(&this.end,0); 142 } 143 void run() 144 { 145 pcnt = 0; 146 ptr = 0; 147 while(true) 148 { 149 instructions[pcnt].dg(instructions[pcnt].value); 150 pcnt++; 151 } 152 } 153 }