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
                });
            }
        }
        public override Action GetStepAction(CancellationToken cancel)
        {
            return(() =>
            {
                if (Analyzer == null)
                {
                    lock (this)
                    {
                        if (Analyzer == null)
                        {
                            Analyzer = new ApteridAnalyzer(Context, ParseUnit.SourceFile, Unit);
                        }
                    }
                }

                try
                {
                    Analyzer.Analyze(cancel);
                }
                catch (OperationCanceledException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    Unit.AddError(new AnalyzerError {
                        Exception = e
                    });
                }
            });
        }
Example #3
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)
                });
            }
        }
        public void Analyze(CancellationToken cancel)
        {
            var sourceNode = SourceFile.ParseTree as Parse.Syntax.Source;

            if (sourceNode == null)
            {
                Unit.AddError(new AnalyzerError
                {
                    ErrorNode = SourceFile.ParseTree,
                    Message   = string.Format(ErrorMessages.E_0010_Analyzer_ParseTreeIsNotSource, SourceFile.Name)
                });
                return;
            }

            var modules = AnalyzeSource(sourceNode, cancel).Result;

            if (Unit.Errors.Any() && Context.AbortOnError)
            {
                return;
            }

            ResolveTypes(modules, cancel);
        }
        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));
        }
        void AnalyzeBinding(Module module, Parse.Syntax.Binding bindingNode, Binding binding, CancellationToken cancel)
        {
            if (bindingNode.Body == null || !bindingNode.Body.Any())
            {
                Unit.AddError(new AnalyzerError
                {
                    ErrorNode = bindingNode,
                    Message   = string.Format(ErrorMessages.E_0014_Analyzer_EmptyBinding, bindingNode.Name.Text),
                });
                return;
            }

            var        triviaNodes = new List <Parse.Syntax.Node>();
            Expression expression  = null;

            Parse.Syntax.Literal literalNode;
            Parse.Syntax.Literal <BigInteger> bigIntLiteral;

            foreach (var node in bindingNode.Body)
            {
                if (cancel.IsCancellationRequested)
                {
                    throw new OperationCanceledException(cancel);
                }

                if ((literalNode = node as Parse.Syntax.Literal) != null)
                {
                    if ((bigIntLiteral = literalNode as Parse.Syntax.Literal <BigInteger>) != null)
                    {
                        expression = new Expressions.IntegerLiteral(bigIntLiteral.Value)
                        {
                            SyntaxNode = bigIntLiteral
                        };
                    }
                    else
                    {
                        throw new NotImplementedException(string.Format("Literals of type {0} not implemented yet.", literalNode.ValueType.Name));
                    }
                }
                else if (node is Parse.Syntax.Space)
                {
                    triviaNodes.Add(node);
                }
            }

            if (expression == null)
            {
                Unit.AddError(new AnalyzerError
                {
                    ErrorNode = bindingNode,
                    Message   = string.Format(ErrorMessages.E_0014_Analyzer_EmptyBinding, bindingNode.Name.Text),
                });
                return;
            }

            foreach (var tn in triviaNodes)
            {
                expression.PostTrivia.Add(tn);
            }

            binding.Expression = expression;
        }
        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));
        }
Example #8
0
        public override Action GetStepAction(CancellationToken cancel)
        {
            return(() =>
            {
                try
                {
                    // set up compilation units
                    if (Unit.ParseUnits == null)
                    {
                        Unit.ParseUnits = Unit.SourceFiles
                                          .Where(sf => (Unit.Mode & CompileOutputMode.SaveToFile) == 0 ||
                                                 Context.ForceRecompile ||
                                                 !sf.Exists ||
                                                 Unit.OutputFileInfo == null ||
                                                 sf.LastWriteTimeUtc > Unit.OutputFileInfo.LastWriteTimeUtc)
                                          .Select(sf => new ParseUnit {
                            SourceFile = sf
                        })
                                          .ToList();
                    }

                    // TODO: make dummy modules from references

                    if (Unit.AnalysisUnit == null)
                    {
                        lock (Unit)
                        {
                            if (Unit.AnalysisUnit == null)
                            {
                                Unit.AnalysisUnit = new AnalysisUnit
                                {
                                    ParseUnits = Unit.ParseUnits
                                };
                            }
                        }
                    }

                    if (Unit.GenerationUnit == null)
                    {
                        lock (Unit)
                        {
                            if (Unit.GenerationUnit == null)
                            {
                                Unit.GenerationUnit = new GenerationUnit
                                {
                                    Mode = Unit.Mode,
                                    ParseUnits = Unit.ParseUnits,
                                    AnalysisUnit = Unit.AnalysisUnit,
                                };
                            }
                        }
                    }

                    // tasks
                    var parseAndAnalyzeActions = new List <Tuple <Action, Action> >();

                    foreach (var parseUnit in Unit.ParseUnits)
                    {
                        Action parse = null;
                        Action analyze = null;

                        if ((Unit.Mode & CompileOutputMode.Parse) != 0)
                        {
                            parse = new ParseSourceFile(Context, parseUnit).GetStepAction(Context.CancelSource.Token);
                        }

                        if ((Unit.Mode & CompileOutputMode.Analyze) != 0)
                        {
                            analyze = new AnalyzeSourceFile(Context, Unit.AnalysisUnit, parseUnit).GetStepAction(Context.CancelSource.Token);
                        }

                        parseAndAnalyzeActions.Add(Tuple.Create(parse, analyze));
                    }

                    var tasks = parseAndAnalyzeActions
                                .Select(pa =>
                    {
                        if (pa.Item1 != null && pa.Item2 != null)
                        {
                            var parse = Task.Factory.StartNew(pa.Item1, TaskCreationOptions.AttachedToParent);
                            return parse.ContinueWith(t => pa.Item2());
                        }
                        else if (pa.Item1 != null)
                        {
                            return Task.Factory.StartNew(pa.Item1, TaskCreationOptions.AttachedToParent);
                        }
                        else if (pa.Item2 != null)
                        {
                            return Task.Factory.StartNew(pa.Item2, TaskCreationOptions.AttachedToParent);
                        }
                        else
                        {
                            return null;
                        }
                    })
                                .Where(t => t != null);

                    Task.WhenAll(tasks).Wait();

                    if ((Unit.Mode & CompileOutputMode.Generate) != 0 && !Unit.Errors.Any())
                    {
                        var generate = new GenerateAssembly(Context, Unit).GetStepAction(Context.CancelSource.Token);
                        var task = Task.Factory.StartNew(generate, TaskCreationOptions.AttachedToParent);
                        task.Wait();
                    }
                }
                catch (OperationCanceledException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    Unit.AddError(new CompilerError {
                        Exception = e
                    });
                }
            });
        }
        public override Action GetStepAction(CancellationToken cancel)
        {
            return(() =>
            {
                var sourceFile = Unit.SourceFile;

                // verify that the source file exists
                if (!sourceFile.Exists)
                {
                    Unit.AddError <NodeError>(string.Format(ErrorMessages.E_0006_Compiler_InvalidSourceFile, sourceFile.Name));

                    if (Context.AbortOnError)
                    {
                        return;
                    }
                }

                if (cancel.IsCancellationRequested)
                {
                    throw new OperationCanceledException(cancel);
                }

                // parse
                try
                {
                    if (Unit.Parser == null)
                    {
                        lock (this)
                        {
                            if (Unit.Parser == null)
                            {
                                Unit.Parser = new ApteridParser(handle_left_recursion: true);
                            }
                        }
                    }

                    var parser = Unit.Parser;
                    parser.SourceFile = sourceFile;
                    sourceFile.Parser = parser;

                    var result = parser.GetMatch(sourceFile.Buffer, parser.ApteridSource);
                    sourceFile.MatchResult = result;
                    sourceFile.MatchState = result.MatchState;

                    if (cancel.IsCancellationRequested)
                    {
                        throw new OperationCanceledException(cancel);
                    }

                    if (result.Success)
                    {
                        // check for error sections
                        sourceFile.ParseTree = result.Result;

                        var errorSections = sourceFile.GetNodes <Parse.Syntax.ErrorSection>();
                        foreach (var es in errorSections)
                        {
                            var error = new NodeError
                            {
                                SourceFile = sourceFile,
                                Message = ErrorMessages.E_0007_Parser_SyntaxError,
                                ErrorNode = es,
                                ErrorIndex = es.StartIndex
                            };
                            Unit.AddError(error);
                        }
                    }
                    else
                    {
                        var error = new NodeError
                        {
                            SourceFile = sourceFile,
                            Message = result.Error,
                            ErrorIndex = result.ErrorIndex
                        };

                        Unit.AddError(error);
                    }
                }
                catch (OperationCanceledException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    Unit.AddError(new NodeError {
                        Exception = e
                    });
                }
            });
        }
Example #10
0
        public override Action GetStepAction(CancellationToken cancel)
        {
            return(() =>
            {
                try
                {
                    var saveToFile = (Unit.Mode & CompileOutputMode.SaveToFile) != 0;
                    var emitSymbols = (Unit.Mode & CompileOutputMode.EmitSymbols) != 0;
                    var optimize = (Unit.Mode & CompileOutputMode.Optimize) != 0;

                    if (saveToFile && !Unit.OutputFileInfo.Directory.Exists)
                    {
                        Unit.AddError(new CompilerError {
                            Message = ErrorMessages.E_0016_Compiler_InvalidOutputDir
                        });
                        saveToFile = false;
                    }

                    var access = saveToFile ? AssemblyBuilderAccess.RunAndSave : AssemblyBuilderAccess.Run;
                    var assemblyName = GetAssemblyName();

                    if (Unit.GenerationUnit.AssemblyBuilder == null)
                    {
                        lock (Unit)
                        {
                            if (Unit.GenerationUnit.AssemblyBuilder == null)
                            {
                                var assemblyBuilder = Unit.GenerationUnit.AssemblyBuilder = saveToFile
                                    ? AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, access, Unit.OutputFileInfo.Directory.FullName)
                                    : AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, access);
                                Unit.GenerationUnit.ModuleBuilder = null;

                                if (emitSymbols)
                                {
                                    var modes = DebuggableAttribute.DebuggingModes.Default;
                                    if (!optimize)
                                    {
                                        modes |= DebuggableAttribute.DebuggingModes.DisableOptimizations;
                                    }

                                    var ctor = typeof(DebuggableAttribute).GetConstructor(new[] { typeof(DebuggableAttribute.DebuggingModes) });
                                    var attb = new CustomAttributeBuilder(ctor, new object[] { modes });
                                    assemblyBuilder.SetCustomAttribute(attb);
                                }
                            }
                        }
                    }

                    if (Unit.GenerationUnit.ModuleBuilder == null)
                    {
                        lock (Unit)
                        {
                            if (Unit.GenerationUnit.ModuleBuilder == null)
                            {
                                var moduleBuilder = Unit.GenerationUnit.ModuleBuilder = saveToFile
                                    ? Unit.GenerationUnit.AssemblyBuilder.DefineDynamicModule(Unit.OutputFileInfo.Name, Unit.OutputFileInfo.Name, emitSymbols)
                                    : Unit.GenerationUnit.AssemblyBuilder.DefineDynamicModule(Unit.OutputFileInfo.Name, emitSymbols);

                                if (emitSymbols)
                                {
                                    foreach (var sf in Unit.SourceFiles)
                                    {
                                        Unit.GenerationUnit.SymbolDocs[sf.Name] = moduleBuilder.DefineDocument(sf.Name,
                                                                                                               SourceFile.ApteridLanguageId, SourceFile.ApteridLanguageVendorId, SourceFile.ApteridLanguageSourceFileId);
                                    }
                                }
                            }
                        }
                    }

                    var generators = Unit.AnalysisUnit.Modules.Values
                                     .Select(m => Task.Factory.StartNew(new GenerateModule(Context, Unit.GenerationUnit, m)
                                                                        .GetStepAction(Context.CancelSource.Token),
                                                                        TaskCreationOptions.AttachedToParent))
                                     .ToArray();

                    Task.WaitAll(generators);

                    if ((Unit.Mode & CompileOutputMode.SaveToFile) != 0)
                    {
                        var emit = Task.Factory.StartNew(new EmitAssembly(Context, Unit)
                                                         .GetStepAction(Context.CancelSource.Token),
                                                         TaskCreationOptions.AttachedToParent);
                        emit.Wait();
                    }
                }
                catch (OperationCanceledException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    Unit.AddError(new GeneratorError {
                        Exception = e
                    });
                }
            });
        }