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));
        }
        void ResolveTypes(IEnumerable <Module> modules, CancellationToken cancel)
        {
            var trr = new TypeResolveRec
            {
                Constraint  = s => new[] { s }, // true
                ExpTypeVars = Enumerable.Empty <Tuple <Expression, Var> >(),
            };

            trr = modules.Aggregate(trr, (mtr, m) =>
            {
                if (cancel.IsCancellationRequested)
                {
                    throw new OperationCanceledException(cancel);
                }

                return(m.Bindings.Values.Aggregate(mtr, (btr, b) =>
                {
                    if (cancel.IsCancellationRequested)
                    {
                        throw new OperationCanceledException(cancel);
                    }

                    return ResolveExpressionType(btr, b.Expression);
                }));
            });

            try
            {
                var varTypes = Goal.Eval(trr.Constraint).First();

                foreach (var expVar in trr.ExpTypeVars)
                {
                    var e = expVar.Item1;
                    var v = expVar.Item2;

                    if (varTypes.Binds(v))
                    {
                        e.ResolvedType = varTypes[v];
                    }
                    else
                    {
                        Unit.AddError(new AnalyzerError
                        {
                            ErrorNode = e.SyntaxNode,
                            Message   = string.Format(ErrorMessages.E_0015_Analyzer_UnableToInferType, ApteridError.Truncate(e.SyntaxNode.Text)),
                        });
                    }
                }
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception e)
            {
                Unit.AddError(new AnalyzerError {
                    Exception = e
                });
            }
        }
Example #4
0
        void GenerateLiteralBinding(GenerateTypeInfo typeInfo, Analyze.Binding binding, Analyze.Expressions.Literal literal)
        {
            if (literal.ResolvedType == null)
            {
                Unit.AddError(new GeneratorError
                {
                    Message   = string.Format(ErrorMessages.E_0017_Generator_UnresolvedType, ApteridError.Truncate(literal.SyntaxNode.Text)),
                    ErrorNode = literal.SyntaxNode
                });
                return;
            }

            var atts = FieldAttributes.Static | FieldAttributes.InitOnly;

            atts |= binding.IsPublic ? FieldAttributes.Public : FieldAttributes.Private;
            var field = typeInfo.TypeBuilder.DefineField(binding.Name.Name, literal.ResolvedType.CLRType, atts);

            typeInfo.Bindings.Add(literal, field);

            if (literal.Value == null)
            {
                if (field.FieldType.IsValueType)
                {
                    field.SetConstant(Activator.CreateInstance(field.FieldType));
                }
                else
                {
                    field.SetConstant(null);
                }
            }
            else
            {
                typeInfo.StaticFieldsToInit.Add(new FieldInitInfo
                {
                    Node    = binding.SyntaxNode,
                    Field   = field,
                    GenLoad = il => GenerateLoadLiteral(il, literal, field.FieldType)
                });
            }
        }