/// <summary> /// Constructs a new <see cref="LoopContext"/> instance. /// </summary> /// <param name="function">The function that contains this loop. Must not be null.</param> /// <param name="writer">The <see cref="ByteCodeWriter"/>.</param> public LoopContext(CompileTimeUserFunction?function, ByteCodeWriter writer) { Debug.Assert(function != null); Function = function; Writer = writer; ContinueIP = StartIP = Writer.IP; BreakFixups = new(); ContinueFixups = new(); // Push this on the function's loop stack Function.LoopContexts.Push(this); }
/// <summary> /// Constructs a new <see cref="Compiler"/> instance. /// </summary> public Compiler() { IntrinsicFunctions = new OrderedDictionary <string, IntrinsicFunction>(StringComparer.OrdinalIgnoreCase); IntrinsicVariables = new OrderedDictionary <string, Variable>(StringComparer.OrdinalIgnoreCase); MaxErrors = 45; CreateLogFile = false; LogFile = null; EnableLineNumbers = true; EnableInternalFunctions = true; Functions = new OrderedDictionary <string, Function>(StringComparer.OrdinalIgnoreCase); Variables = new OrderedDictionary <string, Variable>(StringComparer.OrdinalIgnoreCase); Literals = new List <Variable>(); Lexer = new LexicalAnalyzer(); Lexer.Error += Lexer_Error; Writer = new ByteCodeWriter(Lexer); Errors = new List <Error>(); }
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); }