private bool InternalCompile(string source, [NotNullWhen(true)] out CompiledProgram?program) #endif { Functions.Clear(); Variables.Clear(); Literals.Clear(); Lexer.Reset(); Writer.Reset(); InHeader = true; CurrentFunction = null; Errors.Clear(); 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 { // Prepare to parse source code Lexer.Reset(source); // 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) { string?logFile = LogFile; if (logFile == null) { if (SourceFile != null) { logFile = Path.ChangeExtension(SourceFile, "log"); } else { throw new InvalidOperationException("Unable to create log file : LogFile must be set when no source file name is provided."); } } Writer.WriteLogFile(source, logFile, SourceFile); } // Return compiled data program = new CompiledProgram(Writer.GetBytecodes(), Functions.Values.Select(f => (f is CompileTimeUserFunction userFunction) ? new UserFunction(userFunction) : f).ToArray(), Variables.Values.ToArray(), Literals.ToArray(), EnableLineNumbers ? Writer.GetLineNumbers() : null); return(true); }
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); }