Пример #1
0
 /// <summary>
 /// Directly replace the the corresponding Segment by Blanks, preserving '\r' and '\n'
 /// characters.
 /// </summary>
 /// <param name="curSourceText"></param>
 /// <param name="from">The start position in the buffer</param>
 /// <param name="to">The ending position in the buffer</param>
 private void ReplaceByBlanks(StringSourceText sourceText, int from, int to)
 {
     for (int i = from; i < to; i++)
     {
         char c = sourceText[i];
         sourceText[i] = (c == '\r' || c == '\n' || Char.IsWhiteSpace(c)) ? c : ' ';
     }
 }
Пример #2
0
 /// <summary>
 /// Create a Delete string Corresponding to a segment in a buffer.
 /// We want to create a replacement string that only contains whitespaces
 /// and '\r' or \n' characters.
 /// </summary>
 /// <param name="curSourceText"></param>
 /// <param name="from">The start position in the buffer</param>
 /// <param name="to">The ending position in the buffer</param>
 /// <returns>The replacement characters</returns>
 protected char[] GetDeleteString(StringSourceText sourceText, int from, int to)
 {
     char[] result = new char[to - from];
     for (int i = 0; i < result.Length; i++)
     {
         char c = sourceText[from + i];
         result[i] = (c == '\r' || c == '\n' || Char.IsWhiteSpace(c)) ? c : ' ';
     }
     return(result);
 }
Пример #3
0
        static SourceText?TryLoadSourceText(string directory, string path)
        {
            var full = Path.GetFullPath(Path.Combine(directory, Path.ChangeExtension(path, ModuleFileNameExtension) !));

            try
            {
                return(StringSourceText.FromAsync(full, File.OpenRead(full)).Result);
            }
            catch (Exception)
            {
                // TODO: Catch more specific exceptions?
                return(null);
            }
        }
Пример #4
0
        int Run(Options options)
        {
            var path = options.Module.FullName;

            if (!options.Module.Exists)
            {
                Log.ErrorLine("Module '{0}' could not be found.", path);
                return(1);
            }

            var loader = new StandardModuleLoader(ModuleLoaderMode.Normal);

            _ = loader.SearchPaths.Add(Path.GetDirectoryName(path) !);

            var text    = StringSourceText.FromAsync(path, File.OpenRead(path)).Result;
            var context = new SyntaxContext();

            try
            {
                var mod = loader.LoadModule(text, context);

                foreach (var decl in mod.Declarations.OfType <Function>())
                {
                    decl.Test();
                }
            }
            catch (ModuleLoadException)
            {
                // All errors will be reported in the context.
            }

            foreach (var diag in context.Diagnostics)
            {
                LogDiagnostic(diag);
            }

            // TODO

            return(context.HasDiagnostics ? 1 : 0);
        }
Пример #5
0
        /// <summary>
        /// Perform a linear Generation
        /// //1) A Non commented line with no Associated nodes is generated without any change.
        /// //2) If the line is commented then first comment all following lines that have the same intersection with the corresponding target Nodes.
        /// //3) For each node related to a line, and not already generated the corresponding code.
        /// //4) Flush of Function declations.
        /// <param name="mapper">The linearization representation</param>
        /// <param name="Input">Input source lines</param>
        /// <returns>The Generated Source Document</returns>
        /// </summary>
        private SourceText LinearGeneration <A>(LinearNodeSourceCodeMapper mapper, IReadOnlyList <A> Input) where A : ITextLine
        {
            SourceText targetSourceText = new GapSourceText();
            //Stack Used to save current generation buffer when switching in a function declaration generation.
            //Beacuse a function declartion has its own buffer.
            Stack <SourceText> stackOuterBuffer = new Stack <SourceText>();
            Stack <SourceText> stackLocalBuffer = new Stack <SourceText>();
            //Bit Array of Generated Nodes.
            BitArray generated_node = new BitArray(mapper.NodeCount);

            //For detecting line having characters in columns [73-80]
            Lines_73_80_Flags = new HashSet <int>();
            //The previous line generation buffer
            StringSourceText previousBuffer = null;

            for (int i = 0; i < mapper.LineData.Length; i++)
            {
                //--------------------------------------------------------------------------------------------------------------
                //1) A Non commented line with no Associated nodes is generated without any change.
                if (!mapper.CommentedLines[i] && mapper.LineData[i].LineNodes == null)
                {
                    //If there was a previous buffer ==> Flush it
                    if (previousBuffer != null)
                    {
                        if (!mapper.IsGeneratedEmptyBuffer(previousBuffer))
                        {
                            AppendBufferContent(targetSourceText, previousBuffer);
                        }
                        previousBuffer = null;
                    }
                    string text = Input[i].Text;
                    if (mapper.LineData[i].Buffer != null)
                    {//This line has been assigned a target Buffer
                        mapper.LineData[i].Buffer.Insert(text, targetSourceText.Size, targetSourceText.Size);
                        mapper.LineData[i].Buffer.Insert(Environment.NewLine, targetSourceText.Size, targetSourceText.Size);
                    }
                    else
                    {
                        targetSourceText.Insert(text, targetSourceText.Size, targetSourceText.Size);
                        targetSourceText.Insert(Environment.NewLine, targetSourceText.Size, targetSourceText.Size);
                    }
                    continue;
                }
                //--------------------------------------------------------------------------------------------------------------
                //2) If the line is commented then first comment all following lines that have the same intersection with
                // the corresponding target Nodes.
                List <int> line_nodes = mapper.LineData[i].LineNodes;
                //If there was a previous buffer ==> Flush it
                if (previousBuffer != null && mapper.CommentedLines[i])
                {
                    if (!mapper.IsGeneratedEmptyBuffer(previousBuffer))
                    {
                        AppendBufferContent(targetSourceText, previousBuffer);
                    }
                    previousBuffer = null;
                }
                for (int j = i; mapper.CommentedLines[j]; j++)
                {
                    List <int> current_nodes = mapper.LineData[j].LineNodes;
                    if (!LinearNodeSourceCodeMapper.HasIntersection(line_nodes, current_nodes))
                    {
                        break;//This commented line has no nodes which intersect with the previous line.
                    }
                    IEnumerable <ITextLine> lines = Indent(Input[j], true);
                    foreach (var line in lines)
                    {
                        string text = line.Text.TrimEnd();
                        targetSourceText.Insert(text, targetSourceText.Size, targetSourceText.Size);
                        targetSourceText.Insert(Environment.NewLine, targetSourceText.Size, targetSourceText.Size);
                        CheckFunctionDeclCommentedheader(mapper, current_nodes, text);
                    }
                    mapper.CommentedLines[j] = false;//This commented line has been generated now
                    line_nodes = current_nodes;
                }
                //--------------------------------------------------------------------------------------------------------------
                //3)For each node related to this line, and not already generated.
                line_nodes = mapper.LineData[i].LineNodes;
                foreach (int node_index in line_nodes)
                {
                    if (node_index == -1 || mapper.Nodes[node_index].node.IsFlagSet(Node.Flag.GeneratorCanIgnoreIt))
                    {//bad Node
                        continue;
                    }
                    if (generated_node[node_index])
                    {
                        continue;                                                                           //Already Generated.
                    }
                    bool             bFunctionBodyNode = mapper.Nodes[node_index].FunctionBodyNode != null; //Is this node in a function body ?
                    StringSourceText curSourceText     = mapper.Nodes[node_index].Buffer;
                    if (curSourceText != previousBuffer && previousBuffer != null)
                    {//Flush previous buffer
                        if (!mapper.IsGeneratedEmptyBuffer(previousBuffer))
                        {
                            AppendBufferContent(targetSourceText, previousBuffer);
                        }
                        previousBuffer = null;
                    }
                    Node node                = mapper.Nodes[node_index].node;
                    bool bGenerated          = node is Generated;
                    bool bForceGenerateLines = true;
                    if (!bGenerated)
                    {   //This Node is not Generated: If it removed then remove its source code otherwise do Nothing it is already in the source buffer.
                        bForceGenerateLines = false;
                        if (mapper.Nodes[node_index].Removed)
                        {//If this node is removed
                            //var sourceLine = TargetDocument[i];
                            Position from = mapper.Nodes[node_index].From;
                            Position to   = mapper.Nodes[node_index].To;
                            //Delete <==> Replace with blanks
                            ReplaceByBlanks(curSourceText, from.Pos, to.Pos);
                        }
                        else if (mapper.Nodes[node_index].node.IsFlagSet(Node.Flag.ForceGetGeneratedLines))
                        {//As lines to generate and replace
                            bForceGenerateLines = true;
                        }
                    }
                    if (bForceGenerateLines)
                    {
                        bool     bIsFunctionDecl = mapper.Nodes[node_index] is LinearNodeSourceCodeMapper.NodeFunctionData;
                        bool     bFirst          = true;
                        Position from            = mapper.Nodes[node_index].From;
                        Position to = mapper.Nodes[node_index].To;
                        bool     bIsGenerateAndReplace = node is GeneratedAndReplace;
                        if (bIsGenerateAndReplace)
                        {//The node has a source code that must be replaced
                            string code = (node as GeneratedAndReplace).ReplaceCode;
                            GenerateIntoBufferCheckLineExceed(from, to, curSourceText, code, i + 1);
                        }
                        else
                        {
                            foreach (var line in NodeLines(node, generated_node))
                            {
                                bool         bInsertSplit = false;
                                StringWriter sw           = new StringWriter();
                                if (bFirst && !bIsFunctionDecl && curSourceText != null)
                                {//The first element don't ident it just insert it a the right position
                                 //issue #892 => Anyway Handle splitting
                                    sw.WriteLine(line.Text);
                                    bFirst       = false;
                                    bInsertSplit = true;
                                }
                                else
                                {
                                    foreach (var l in Indent(line, null))
                                    {
                                        sw.WriteLine(l.Text.TrimEnd());
                                    }
                                }
                                sw.Flush();
                                string text = sw.ToString();
                                if (bIsFunctionDecl)
                                { //This the Function Header output.
                                    LinearNodeSourceCodeMapper.NodeFunctionData funData = mapper.Nodes[node_index] as LinearNodeSourceCodeMapper.NodeFunctionData;
                                    int f = Math.Min(from.Pos, curSourceText.Size);
                                    int t = Math.Min(to.Pos, curSourceText.Size);
                                    if (f != t)
                                    {
                                        //Create a the erase string to erase in the original source code
                                        //The Function header.
                                        //Erase in the original source code the Function header?
                                        ReplaceByBlanks(curSourceText, f, t);
                                        //Output the pre-stored comment header
                                        InsertLineMaybeSplit(funData.FunctionDeclBuffer, funData.CommentedHeader.ToString(), funData.FunctionDeclBuffer.Size, funData.FunctionDeclBuffer.Size, bInsertSplit);
                                    }
                                    //Insert the sequence
                                    InsertLineMaybeSplit(funData.FunctionDeclBuffer, text, funData.FunctionDeclBuffer.Size, funData.FunctionDeclBuffer.Size, bInsertSplit);
                                }
                                else
                                {
                                    if (curSourceText == null)
                                    {
                                        InsertLineMaybeSplit(targetSourceText, text, targetSourceText.Size, targetSourceText.Size, bInsertSplit);
                                    }
                                    else
                                    {
                                        InsertLineMaybeSplit(curSourceText, text, Math.Min(from.Pos, curSourceText.Size), Math.Min(to.Pos, curSourceText.Size), bInsertSplit);
                                    }
                                }
                                from = to;
                                sw.Close();
                            }
                        }
                        //Don't pad in case of replacement or insertion in a function declaration
                        if (!bIsGenerateAndReplace && !bIsFunctionDecl)
                        {
                            //Pad a splitted segment
                            if (mapper.Nodes[node_index].Positions != null)
                            {
                                int    span = mapper.Nodes[node_index].Positions.Item3;
                                string pad  = new string(' ', span);
                                curSourceText.Insert(pad, to.Pos, to.Pos);
                            }
                        }
                        if (bIsFunctionDecl)
                        {   //Switch in function declaration -> push the current buffers
                            LinearNodeSourceCodeMapper.NodeFunctionData funData = mapper.Nodes[node_index] as LinearNodeSourceCodeMapper.NodeFunctionData;
                            stackLocalBuffer.Push(curSourceText);
                            stackOuterBuffer.Push(targetSourceText);
                            //Now Generate in Function Declaration Buffer.
                            targetSourceText = funData.FunctionDeclBuffer;
                            curSourceText    = null;
                        }
                    }
                    //This node is now generated.
                    generated_node[node_index] = true;
                    if (mapper.Nodes[node_index].node.IsFlagSet(Node.Flag.EndFunctionDeclarationNode))
                    {   //Leaving function declaration --> Pop saved buffers.
                        if (previousBuffer != null)
                        {
                            if (!mapper.IsGeneratedEmptyBuffer(previousBuffer))
                            {
                                AppendBufferContent(targetSourceText, previousBuffer);
                            }
                            previousBuffer = null;
                        }
                        System.Diagnostics.Debug.Assert(stackOuterBuffer.Count > 0 && stackLocalBuffer.Count > 0);
                        if (stackOuterBuffer.Count > 0 && stackLocalBuffer.Count > 0)
                        {
                            targetSourceText = stackOuterBuffer.Pop();
                            curSourceText    = (StringSourceText)stackLocalBuffer.Pop();
                        }
                        previousBuffer = curSourceText;
                    }
                    else
                    {
                        previousBuffer = curSourceText;
                    }
                }
                //--------------------------------------------------------------------------------------------------------------
            }
            //If there was a previous buffer ==> Flush it
            if (previousBuffer != null)
            {
                if (!mapper.IsGeneratedEmptyBuffer(previousBuffer))
                {
                    AppendBufferContent(targetSourceText, previousBuffer);
                }
                previousBuffer = null;
            }
            //--------------------------------------------------------------------------------------------------------------
            //4)//Flush of Function declation body
            foreach (int fun_index in mapper.FunctionDeclarationNodeIndices)
            {
                LinearNodeSourceCodeMapper.NodeFunctionData funData = mapper.Nodes[fun_index] as LinearNodeSourceCodeMapper.NodeFunctionData;
                AppendBufferContent(targetSourceText, funData.FunctionDeclBuffer);
            }
            //5)//Generate Line Exceed Diagnostics
            GenerateExceedLineDiagnostics();
            return(targetSourceText);
        }
Пример #6
0
        protected override SourceText?GetSourceText(ModulePath path)
        {
            // Core modules are not subject to any security checks, so make sure they're not loaded
            // from arbitrary file system locations.
            if (path.IsCore)
            {
                try
                {
                    var rsc    = $"{nameof(Flare)}.{string.Join('.', path.Components)}.{ModuleFileNameExtension}";
                    var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(rsc);

                    return(stream != null?StringSourceText.FromAsync(Path.Combine(_assemblyPath, rsc),
                                                                     stream).Result : null);
                }
                catch (Exception e)
                {
                    throw new ModuleLoadException($"Core module '{path}' failed to load: {e.Message}", e);
                }
            }

            var str = string.Join(Path.DirectorySeparatorChar, path.Components);

            foreach (var dir in SearchPaths)
            {
                if (TryLoadSourceText(dir, str) is SourceText source)
                {
                    return(source);
                }
            }

            if (!UseEnvironmentVariable)
            {
                return(null);
            }

            foreach (var dir in GetSearchPaths(EnvironmentVariableTarget.Process))
            {
                if (TryLoadSourceText(dir, str) is SourceText source)
                {
                    return(source);
                }
            }

            foreach (var dir in GetSearchPaths(EnvironmentVariableTarget.User))
            {
                if (TryLoadSourceText(dir, str) is SourceText source)
                {
                    return(source);
                }
            }

            foreach (var dir in GetSearchPaths(EnvironmentVariableTarget.Machine))
            {
                if (TryLoadSourceText(dir, str) is SourceText source)
                {
                    return(source);
                }
            }

            return(null);
        }
Пример #7
0
        int Run(Options options)
        {
            ReadLine.AutoCompletionHandler = null;

            var loader = new StandardModuleLoader(ModuleLoaderMode.Interactive);
            var i      = 0;

            while (true)
            {
                Console.ForegroundColor = ConsoleColor.Cyan;
                Console.Write($"flare({i})> ");
                Console.ResetColor();

                var text      = new StringBuilder();
                var quit      = false;
                var continued = false;

                while (true)
                {
                    var input = ReadLine.Read();

                    if (input != string.Empty)
                    {
                        ReadLine.AddHistory(input);
                    }

                    var broken = false;

                    if (input == "'repl:quit")
                    {
                        quit = true;
                        break;
                    }
                    if (continued && input == "'repl:break")
                    {
                        broken = true;
                    }
                    else
                    {
                        _ = text.AppendLine(input);
                    }

                    var lex = LanguageLexer.Lex(StringSourceText.From("<repl>", text.ToString()));

                    foreach (var diag in lex.Diagnostics)
                    {
                        LogDiagnostic(diag);
                    }

                    if (!lex.IsSuccess)
                    {
                        break;
                    }

                    var parse = LanguageParser.Parse(lex, SyntaxMode.Interactive);

                    if (!broken && IsIncomplete(parse))
                    {
                        Console.ForegroundColor = ConsoleColor.Cyan;
                        Console.Write($".....({i})> ");
                        Console.ResetColor();

                        continued = true;

                        continue;
                    }

                    foreach (var diag in parse.Diagnostics)
                    {
                        LogDiagnostic(diag);
                    }

                    var analysis = LanguageAnalyzer.Analyze(parse, loader, new SyntaxContext());

                    foreach (var diag in analysis.Diagnostics)
                    {
                        LogDiagnostic(diag);
                    }

                    break;
                }

                if (quit)
                {
                    break;
                }

                i++;
            }

            return(0);
        }