Task <Module[]> AnalyzeSource(Parse.Syntax.Source sourceNode, CancellationToken cancel) { var nodesAndModules = new List <Tuple <Parse.Syntax.Module, Module> >(); // collect top-level modules var triviaNodes = new List <Parse.Syntax.Node>(); Module curModule = null; Parse.Syntax.Module moduleNode = null; foreach (var node in sourceNode.Children) { if (cancel.IsCancellationRequested) { throw new OperationCanceledException(cancel); } if ((moduleNode = node as Parse.Syntax.Module) != null) { // look for existing module var moduleName = new QualifiedName { Qualifiers = moduleNode.Qualifiers.Select(id => id.Text), Name = moduleNode.Name.Text }; lock (Unit.Modules) { if (!Unit.Modules.TryGetValue(moduleName, out curModule)) { curModule = new Module { Name = moduleName }; Unit.Modules.Add(curModule.Name, curModule); } foreach (var tn in triviaNodes) { curModule.PreTrivia.Add(tn); } triviaNodes.Clear(); } nodesAndModules.Add(Tuple.Create(moduleNode, curModule)); } else if (node is Parse.Syntax.Directive) { throw new NotImplementedException(); } else if (node is Parse.Syntax.Space) { triviaNodes.Add(node); } else { Unit.AddError(new AnalyzerError { ErrorNode = node, Message = string.Format(ErrorMessages.E_0011_Analyzer_InvalidToplevelItem, ApteridError.Truncate(node.Text)), }); } } if (curModule != null) { foreach (var tn in triviaNodes) { curModule.PostTrivia.Add(tn); } } // analyze var tasks = nodesAndModules.Select(mm => AnalyzeModule(mm.Item1, mm.Item2, cancel)); return(Task.WhenAll(tasks)); }
Task <Module> AnalyzeModule(Parse.Syntax.Module moduleNode, Module module, CancellationToken cancel) { var bindings = new List <Tuple <Parse.Syntax.Binding, Binding> >(); // collect module bindings var triviaNodes = new List <Parse.Syntax.Node>(); Binding curBinding = null; Parse.Syntax.Binding bindingNode = null; foreach (var node in moduleNode.Body) { if (cancel.IsCancellationRequested) { throw new OperationCanceledException(cancel); } if ((bindingNode = node as Parse.Syntax.Binding) != null) { var bindingName = new QualifiedName(module, bindingNode.Name.Text); lock (module.Bindings) { if (module.Bindings.TryGetValue(bindingName, out curBinding)) { Unit.AddError(new AnalyzerError { ErrorNode = node, Message = string.Format(ErrorMessages.E_0012_Analyzer_DuplicateBinding, bindingName.Name), }); } else { curBinding = new Binding { Parent = module, Name = bindingName, SyntaxNode = bindingNode }; bindings.Add(Tuple.Create(bindingNode, curBinding)); module.Bindings.Add(curBinding.Name, curBinding); } foreach (var tn in triviaNodes) { curBinding.PreTrivia.Add(tn); } triviaNodes.Clear(); } } else if (node is Parse.Syntax.Space) { triviaNodes.Add(node); } else { Unit.AddError(new AnalyzerError { ErrorNode = node, Message = string.Format(ErrorMessages.E_0013_Analyzer_InvalidScopeItem, ApteridError.Truncate(node.Text)), }); } } if (curBinding != null) { foreach (var tn in triviaNodes) { curBinding.PostTrivia.Add(tn); } } // analyze var tasks = bindings.Select(bb => Task.Factory.StartNew(() => AnalyzeBinding(module, bb.Item1, bb.Item2, cancel), TaskCreationOptions.AttachedToParent)); return(Task.WhenAll(tasks).ContinueWith(t => module)); }