private void _function() { byte id = Pop(); BytecodeFunction function = _functions[id]; if (function == null) { throw new Exception($"function_{id} not defined."); } Console.WriteLine($"Running function_{id}"); byte[] results = _interpretFunction(function); if (results == null || results.Length == 0) { return; } //TODO: check that this is all happening in order for (int i = 0; i < results.Length; i++) { Push(results[0]); } }
public byte[] Interpret(IList <byte> bytes) //TODO: should take a stack? { BytecodeFunction function = new BytecodeFunction(bytes); _interpretFunction(function); return(_interpretFunction(_functions[0])); }
private void _defFunction(List <byte> bytes, ref int i) { byte id = Pop(); BytecodeFunction function = new BytecodeFunction(); byte functionCount = 1; bool shouldEscapeWhileLoop = false; while (i < bytes.Count) { // Read the next byte from the bytecode. byte value = bytes[++i]; InstructionsEnum instruction = (InstructionsEnum)value; //skip all instructions until we hit end function (still shift i for literals though) switch (instruction) { case InstructionsEnum.DefFunction: functionCount++; //TODO: consider order and things function.Instructions.Add(value); break; case InstructionsEnum.EndDefFunction: functionCount--; if (functionCount == 0) { shouldEscapeWhileLoop = true; } else { function.Instructions.Add(value); } break; case InstructionsEnum.Literal: //TODO: consider order and things function.Instructions.Add(value); function.Instructions.Add(bytes[++i]); break; default: //TODO: consider order and things function.Instructions.Add(value); break; } if (shouldEscapeWhileLoop) { break; } } Console.WriteLine($"Defining function_{id}"); _functions[id] = function; }
private void _returnSignature(BytecodeFunction function) { function.ReturnType = Pop(); function.ShouldReturnArray = (Pop() == 1); if (function.ShouldReturnArray) { Console.WriteLine($"Setting signature to return type_{function.ReturnType}[]"); } else { Console.WriteLine($"Setting signature to return type_{function.ReturnType}"); } }
private byte[] _return(BytecodeFunction function) { if (function.ReturnType == 0) { Console.Write($"Returning null"); return(null); } byte[] returnBytes; if (function.ShouldReturnArray) { byte arrayLength = Pop(); byte numFields = _types[function.ReturnType]; Console.WriteLine($"Returning a type_{function.ReturnType}[]"); returnBytes = new byte[arrayLength * numFields]; for (int i = 0; i < arrayLength; i++) { for (int j = 0; j < numFields; j++) { returnBytes[(i * numFields) + (numFields - 1 - j)] = Pop(); //(numFields-1-j) is to ensure that we reverse the order they would otherwise appear in in the stack } } return(returnBytes); } Console.WriteLine($"Returning a type_{function.ReturnType}"); returnBytes = new byte[function.ReturnType]; for (byte i = 0; i < function.ReturnType; i++) { returnBytes[i] = Pop(); } return(returnBytes); }
private byte[] _interpretFunction(BytecodeFunction function) { Console.WriteLine(this); int size = function.Instructions.Count; for (int i = 0; i < size; i++) { InstructionsEnum instruction = (InstructionsEnum)function.Instructions[i]; //if we're in an if and the status is false if (ifs.Count > 0 && ifs.Peek() == false) { //skip all instructions until we hit end if (still shift i for literals though) switch (instruction) { case InstructionsEnum.If: ifs.Push(false); //push a false so we can handle nested ifs continue; case InstructionsEnum.Literal: i++; continue; case InstructionsEnum.EndIf: break; default: continue; } } switch (instruction) { case InstructionsEnum.Literal: _literal(function.Instructions, ref i); break; case InstructionsEnum.ReturnSignature: _returnSignature(function); break; case InstructionsEnum.Add: //should be preceded by two values to add _add(); break; case InstructionsEnum.Subtract: //should be preceded by two values to subtract _subtract(); break; case InstructionsEnum.Multiply: //should be preceded by two values to multiply _multiply(); break; case InstructionsEnum.Divide: //should be preceded by two values to divide _divide(); break; case InstructionsEnum.LessThan: _lessThan(); break; case InstructionsEnum.GreaterThan: _greaterThan(); break; case InstructionsEnum.EqualTo: _equalTo(); break; case InstructionsEnum.GreaterThanOrEqualTo: _greaterThanOrEqualTo(); break; case InstructionsEnum.LessThanOrEqualTo: _lessThanOrEqualTo(); break; case InstructionsEnum.If: _if(); break; case InstructionsEnum.EndIf: _endIf(); break; case InstructionsEnum.For: _for(i); break; case InstructionsEnum.EndFor: _endFor(ref i); break; case InstructionsEnum.DefArray: _defArray(); break; case InstructionsEnum.GetArray: _getArray(); break; case InstructionsEnum.GetArrayLength: _getArrayLength(); break; case InstructionsEnum.GetArrayValueAtIndex: _getArrayValueAtIndex(); break; case InstructionsEnum.SetArrayValueAtIndex: _setArrayValueAtIndex(); break; case InstructionsEnum.DefType: _defType(); break; case InstructionsEnum.DefVar: _defVar(); break; case InstructionsEnum.GetVar: _getVar(); break; case InstructionsEnum.SetVar: _setVar(); break; case InstructionsEnum.DefFunction: _defFunction(function.Instructions, ref i); break; case InstructionsEnum.Function: _function(); break; case InstructionsEnum.CustomFunction: _customFunction(); break; case InstructionsEnum.Return: return(_return(function)); } Console.WriteLine(this); } if (function.ReturnType > 0) { throw new Exception("Missing return statement."); } return(null); }