/// <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; }
/// <summary> /// Initializes a new <see cref="Runtime"/> instance and prepares to execute the /// given program. /// </summary> /// <param name="program">The program to prepare to execute.</param> public Runtime(CompiledProgram program) { Reset(program); }
/// <summary> /// Compiles the source code in the specified file to byte codes. /// </summary> /// <param name="source">The source code to compile.</param> /// <param name="program">If successful, returns the compiled program.</param> /// <returns>True if successful, false if there were compile errors.</returns> #if NETSTANDARD2_0 public bool CompileSource(string source, out CompiledProgram program)
/// <summary> /// /// </summary> /// <param name="source"></param> /// <param name="program"></param> /// <returns></returns> #if NETSTANDARD2_0 private bool InternalCompile(string source, out CompiledProgram program)
/// <summary> /// Compiles the source code in the specified file to byte codes. /// </summary> /// <param name="stream">A stream that contains the source code to compile.</param> /// <param name="encoding">The charcter encoding to use.</param> /// <param name="program">If successful, returns the compiled program.</param> /// <returns>True if successful, false if there were compile errors.</returns> #if NETSTANDARD2_0 public bool Compile(Stream stream, Encoding encoding, out CompiledProgram program)
/// <summary> /// Compiles the source code in the specified file to byte codes. /// </summary> /// <param name="stream">A stream that contains the source code to compile.</param> /// <param name="encoding">The character encoding to use.</param> /// <param name="detectEncodingFromByteOrderMarks">Set to true to look for byte order marks at the beginning /// of the file.</param> /// <param name="program">If successful, returns the compiled program.</param> /// <returns>True if successful, false if there were compile errors.</returns> #if NETSTANDARD2_0 public bool Compile(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, out CompiledProgram program)
/// <summary> /// Compiles the source code in the specified file to byte codes. /// </summary> /// <param name="stream">A stream that contains the source code to compile.</param> /// <param name="program">If successful, returns the compiled program.</param> /// <returns>True if successful, false if there were compile errors.</returns> #if NETSTANDARD2_0 public bool Compile(Stream stream, out CompiledProgram program)
/// <summary> /// Compiles the source code in the specified file to byte codes. /// </summary> /// <param name="path">Name of the file that contains the source code to compile.</param> /// <param name="encoding">The character encoding to use.</param> /// <param name="detectEncodingFromByteOrderMarks">Set to true to look for byte order marks at the beginning /// of the file.</param> /// <param name="program">If successful, returns the compiled program.</param> /// <returns>True if successful, false if there were compile errors.</returns> #if NETSTANDARD2_0 public bool Compile(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks, out CompiledProgram program)
/// <summary> /// Compiles the source code in the specified file to byte codes. /// </summary> /// <param name="path">Name of the file that contains the source code to compile.</param> /// <param name="encoding">The character encoding to use.</param> /// <param name="program">If successful, returns the compiled program.</param> /// <returns>True if successful, false if there were compile errors.</returns> #if NETSTANDARD2_0 public bool Compile(string path, Encoding encoding, out CompiledProgram program)
/// <summary> /// Compiles the source code in the specified file to byte codes. /// </summary> /// <param name="path">Name of the file that contains the source code to compile.</param> /// <param name="program">If successful, returns the compiled program.</param> /// <returns>True if successful, false if there were compile errors.</returns> #if NETSTANDARD2_0 public bool Compile(string path, out CompiledProgram program)
public bool Compile(string path, out CompiledProgram program) { Functions = new OrderedDictionary <string, Function>(StringComparer.OrdinalIgnoreCase); Variables = new OrderedDictionary <string, Variable>(StringComparer.OrdinalIgnoreCase); Literals = new List <Variable>(); Lexer = new LexicalAnalyzer(this); Lexer.Error += Lexer_Error; Writer = new ByteCodeWriter(Lexer); InHeader = true; CurrentFunction = null; Errors = new List <Error>(); program = null; // Add intrinsic functions to function collection foreach (var function in IntrinsicFunctions.Values) { Functions.Add(function.Name, function); } // Add intrinsic variables to variable collection foreach (var pair in IntrinsicVariables.GetKeyValuePairs()) { Variables.Add(pair.Key, pair.Value); } // Add internal functions and variables if (EnableInternalFunctions) { InternalFunctions.AddInternalFunctionsAndVariables(Functions, Variables); } try { // Load file and initialize lexer Lexer.Reset(File.ReadAllText(path)); // Write bytecodes to call function main. // Also causes error if main function is not defined Writer.Write(ByteCode.ExecFunction, GetFunctionId(Function.Main)); // Parse statements while (ParseStatement()) { ; } // Verify end of file Token token = Lexer.GetNext(); if (token.Type != TokenType.EndOfFile) { Error(ErrorCode.UnexpectedToken, token); } // Check for undefined functions foreach (var funcInfo in Functions.GetKeyValuePairs()) { if (funcInfo.Value == null) { if (funcInfo.Key.Equals(Function.Main, StringComparison.CurrentCultureIgnoreCase)) { Error(ErrorCode.MainNotDefined, Function.Main.MakeQuoted()); } else { Error(ErrorCode.FunctionNotDefined, funcInfo.Key.MakeQuoted()); } } } } catch (TooManyErrorsException) { // Already handled } catch (Exception ex) { Error(ErrorCode.InternalError, ex.Message, ErrorLevel.FatalError); } // Done if compile failed if (Errors.Count > 0) { return(false); } // Implement logging if (CreateLogFile) { Writer.WriteLogFile(path, Path.ChangeExtension(path, "log")); } // Return compiled data program = new CompiledProgram { ByteCodes = Writer.GetBytecodes(), Functions = Functions.Values.Select(f => (f is CompileTimeUserFunction userFunction) ? new UserFunction(userFunction) : f).ToArray(), Variables = Variables.Values.ToArray(), Literals = Literals.ToArray(), LineNumbers = EnableLineNumbers ? Writer.GetLineNumbers() : null, }; return(true); }