Created
October 24, 2019 21:24
-
-
Save Nafees10/d438de2ac56f93bf455453204fc525c1 to your computer and use it in GitHub Desktop.
Revisions
-
Nafees10 created this gist
Oct 24, 2019 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,265 @@ import std.stdio; import std.datetime.stopwatch; void main(string[] args){ FCall caller; Switcher swExec; StopWatch sw; if (args.hasElement("output")){ caller = new FCall(cast(ubyte[])outputProgramInstructions, cast(int[])outputProgramArgs, 64); swExec = new Switcher(cast(ubyte[])outputProgramInstructions, cast(int[])outputProgramArgs, 64); }else{ caller = new FCall(cast(ubyte[])programInstructions, cast(int[])programArgs, 64); swExec = new Switcher(cast(ubyte[])programInstructions, cast(int[])programArgs, 64); } caller.push(1); swExec.push(1); if (args.hasElement("sw")){ writeln("starting Switcher"); sw.start(); swExec.execute; sw.stop; }else{ writeln("starting FCall"); sw.start(); caller.execute; sw.stop; } writeln("execution took: ", sw.peek.total!"msecs", "msecs"); } /// Instructions: /// 0 : push /// 1 : add /// 2 : isLess /// 3 : jumpIf (to zero) /// 4 : Writeln /// 5 : push popped element twice class Switcher{ private: ubyte[] _program; int[] _args; Stack _stack; public: this(ubyte[] program, int[] args, uint maxStack){ _program = program.dup; _args = args.dup; _stack = new Stack(maxStack); } ~this(){ .destroy(_stack); } /// pushes to stack void push(int element){ _stack.push(element); } /// Executes program void execute(){ int* _argPtr = &_args[0]; ubyte* instPtr = &_program[0]; ubyte* lastInstruction = &_program[_program.length-1] + 1; while (instPtr < lastInstruction){ switch (*instPtr){ case 0: _stack.push(*_argPtr); break; case 1: _stack.push(_stack.pop + _stack.pop); break; case 2: _stack.push(cast(int)(_stack.pop > _stack.pop)); break; case 3: if (_stack.pop == 1){ instPtr = &_program[0] - 1; _argPtr = &_args[0] - 1; } break; case 4: writeln(_stack.pop); break; case 5: int element = _stack.pop; _stack.push([element, element]); default: break; } instPtr++; _argPtr++; } } } class FCall{ private: void delegate(int)[] _program; int[] _args; Stack _stack; void delegate(int)* _instPtr; int* _argPtr; void delegate(int)[ubyte] _instructionTable; void pushRuntime(int a){ _stack.push(a); } void add(int a){ _stack.push(_stack.pop + _stack.pop); } void isLess(int a){ _stack.push(cast(int)(_stack.pop > _stack.pop)); } void jumpIf(int a){ if (_stack.pop == 1){ _instPtr = &_program[0] - 1; _argPtr = &_args[0] - 1; } } void writeLn(int a){ writeln(_stack.pop); } void rePush(int a){ int element = _stack.pop; _stack.push([element, element]); } public: this(ubyte[] program, int[] args, uint maxStack){ _args = args.dup; _stack = new Stack(maxStack); _instructionTable[0] = &this.pushRuntime; _instructionTable[1] = &this.add; _instructionTable[2] = &this.isLess; _instructionTable[3] = &this.jumpIf; _instructionTable[4] = &this.writeLn; _instructionTable[5] = &this.rePush; // translate the program _program.length = program.length; foreach (i, inst; program){ _program[i] = _instructionTable[inst]; } } ~this(){ .destroy(_stack); } /// pushes to stack void push(int element){ _stack.push(element); } /// executes the program void execute(){ _instPtr = &_program[0]; _argPtr = &_args[0]; void delegate(int)* lastInstruction = &_program[_program.length - 1] + 1; while (_instPtr < lastInstruction){ (*_instPtr)(*_argPtr); _instPtr ++; _argPtr ++; } } } /// Fixed max-length stack (not using utils.lists.Stack because that one isnt optimized to be fast as much as this should be) /// /// Be aware that no bound checking is done here, so be careful package class Stack{ private: /// the actual stack int[] _stackArray; /// pointer of the next element that'll be written to next int* _peekPtr; public: this(uint length=64){ _stackArray.length = length; _peekPtr = _stackArray.ptr; } /// Reads n number of elements from stack, in reverse order (i.e: [nth-last pushed, (n-1)th-last pushed, ..., last pushed]) /// /// Returns: the elements read int[] pop(uint n){ _peekPtr -= n; return _peekPtr[0 .. n]; } /// Reads the last element pushed to stack /// /// Returns: the element pop-ed int pop(){ _peekPtr --; return *_peekPtr; } /// pushes elements to stack. First in array is pushed first void push(int[] elements){ _peekPtr[0 .. elements.length] = elements; _peekPtr += elements.length; } /// pushes an element to stack void push(int element){ *_peekPtr = element; _peekPtr ++; } /// Returns: number of elements present @property uint count(){ return cast(uint)(_peekPtr - _stackArray.ptr); } /// Returns: the element at an index (this is possible as the stack is actually an array) int read(uint index){ return _stackArray[index]; } /// Writes a value to an index on the stackArray (possible because the stack is actually a stack) void write(uint index, int value){ _stackArray[index] = value; } } /// program, with output const ubyte[] outputProgramInstructions = [ 0, 1, 5, 4, 5, 0, 2, 3 ]; /// program, with output const int[] outputProgramArgs = [ 1, 0, 0, 0, 0, 1000000 ]; /// program, without output const ubyte[] programInstructions = [ 0, 1, 5, 0, 2, 3 ]; /// program, without output const int[] programArgs = [ 1, 0, 0, 1000000 ]; /// Returns: true if an aray has an element, false if no /// /// I stole it from my repo github/nafees10/utils bool hasElement(T)(T[] array, T element){ bool r = false; foreach(cur; array){ if (cur == element){ r = true; break; } } return r; }