/// <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); }
public void Reset(CompiledProgram program) { Program = program ?? throw new ArgumentNullException(nameof(program)); Reader = new ByteCodeReader(Program.GetByteCodes()); FunctionStack = new Stack <RuntimeFunction>(); VarStack = new Stack <Variable>(); UserData = null; }