/// <summary> /// Executes the given program. /// </summary> /// <param name="program">Program to execute.</param> /// <returns>Returns a variable that contains the result of the program.</returns> public Variable Execute(CompiledProgram program) { if (program == null) { throw new ArgumentNullException(nameof(program)); } if (program.IsEmpty) { throw new Exception("Cannot execute empty program"); } // Populate data Reader = new ByteCodeReader(program.GetByteCodes()); Functions = program.GetFunctions(); Variables = program.GetVariables(); Literals = program.GetLiterals(); FunctionStack = new Stack <RuntimeFunction>(); VarStack = new Stack <Variable>(); UserData = null; OnBegin(); // Initial bytecode is call to main() function ByteCode bytecode = Reader.GetNext(); Debug.Assert(bytecode == ByteCode.ExecFunction); int mainId = Reader.GetNextValue(); Debug.Assert(Functions[mainId] is UserFunction); RuntimeFunction function = new RuntimeFunction(Functions[mainId] as UserFunction); try { // Execute this function ExecuteFunction(function); } catch (Exception ex) { // Include line-number information if possible if (program.LineNumbers != null) { Debug.Assert(program.LineNumbers.Length == program.ByteCodes.Length); int ip = (Reader.IP - 1); if (ip >= 0 && ip < program.LineNumbers.Length) { string s = $"\"{ex.Message}\" exception on line {program.LineNumbers[ip]}. See inner exception for details."; throw new Exception(s, ex); } } throw; } finally { OnEnd(); } // Return result return(function.ReturnValue); }
/// <summary> /// Executes the given program. /// </summary> /// <returns>Returns a variable that contains the result of the program.</returns> public Variable Execute() { Reader.GoTo(0); FunctionStack.Clear(); VarStack.Clear(); UserData = null; OnBegin(); try { // Initial bytecodes are call to main() function ByteCode bytecode = Reader.GetNext(); Debug.Assert(bytecode == ByteCode.ExecFunction); int mainId = Reader.GetNextValue(); // Validate if (bytecode != ByteCode.ExecFunction || Program.Functions[mainId] is not UserFunction userFunction) { throw new Exception("Invalid bytecode program : Missing call to function main."); } RuntimeFunction function = new(userFunction); // Execute this function ExecuteFunction(function); // Return result return(function.ReturnValue); } catch (Exception ex) { // Include line-number information if possible if (Program.LineNumbers != null) { Debug.Assert(Program.LineNumbers.Length == Program.ByteCodes.Length); int ip = (Reader.IP - 1); if (ip >= 0 && ip < Program.LineNumbers.Length) { string s = $"\"{ex.Message}\" exception on line {Program.LineNumbers[ip]}. See inner exception for details."; throw new Exception(s, ex); } } throw; } finally { OnEnd(); } }
private void Jump() { int ip = Reader.GetNextValue(); Debug.Assert(ip != ByteCodes.InvalidIP); Reader.GoTo(ip); }