コード例 #1
0
        private IList <ICompileError> DiagnoseSourceFile(SourceFile sourceFile)
        {
            // NOTE: For now we just parse and check syntax
            var result = new List <ICompileError>();
            // Create a dependency system
            var system = new DependencySystem("../stdlib");
            var symTab = system.SymbolTable;

            // Register for errors
            system.CompileError += (s, err) => result.Add(err);
            // From now on we do semantic checking
            // If at any phase we encounter errors, simply terminate

            // Parse the ast
            var ast = system.ParseAst(sourceFile);

            if (result.Count > 0)
            {
                return(result);
            }

            // Do symbol resolution
            SymbolResolution.Resolve(symTab, ast);
            if (result.Count > 0)
            {
                return(result);
            }

            // Finally type-check
            system.TypeCheck(ast);
            return(result);
        }
コード例 #2
0
        private LocationOrLocationLinks FindDefinition(SourceFile sourceFile, Text.Position position)
        {
            // TODO: A bit redundant to parse again, we need to store ASTs too
            // We could do that in the dependency system or something
            // Also we are instantiating multiple dependency systems

            // Create a dependency system
            var system = new DependencySystem("../stdlib");
            var symTab = system.SymbolTable;
            var ast    = system.ParseAst(sourceFile);

            SymbolResolution.Resolve(symTab, ast);

            var node = FindByPosition.Find(ast, position);

            // NOTE: We wouldn't need the check here, but ReferredSymbol throws...
            // We should avoid that
            if (node is Expression.Identifier ident)
            {
                var symbol = symTab.ReferredSymbol(ident);
                if (symbol.Definition != null && symbol.Definition.ParseTreeNode != null)
                {
                    var treeNode = symbol.Definition.ParseTreeNode;
                    return(new LocationOrLocationLinks(
                               new LocationOrLocationLink(Translator.TranslateLocation(treeNode.Span))));
                }
            }

            return(new LocationOrLocationLinks());
        }
コード例 #3
0
        public override Value Execute(VirtualMachine vm, IEnumerable <Value> args)
        {
            var fileName = GetFileName(vm, args);
            // TODO: Skip if already imported?
            // This could be part of the system so it could just return the proper scope to wrap
            // Or the intrinsic itself could cache already loaded in values
            // Load in file
            // TODO: syntax status?
            var ast = System.LoadAst(fileName);

            // We need to create a struct type that contains the constants in the file
            // First we define the new scope
            System.SymbolTable.PushScope(Semantic.ScopeKind.Struct);
            var structScope = System.SymbolTable.CurrentScope;

            // Define things
            // TODO: compile status?
            SymbolResolution.Resolve(System.SymbolTable, ast);
            // Pop scope
            System.SymbolTable.PopScope();
            // Create the new type
            var moduleType = new Type.Struct(
                structScope,
                new Syntax.Token(new Text.Span(), Syntax.TokenType.KwStruct, "struct"),
                new Dictionary <string, Type.Struct.Field>());

            // Wrap it, return it
            return(new Value.User(moduleType));
        }
コード例 #4
0
        /// <summary>
        /// Adds a TargetInstruction attribute to each intrinsic callable that doesn't have one,
        /// unless the automatically determined target instruction name conflicts with another target instruction name.
        /// The automatically determined name of the target instruction is the lower case version of the unqualified callable name.
        /// Type constructors and generic callables are left unchanged.
        /// </summary>
        /// <returns>Returns true if all missing attributes have been successfully added and false if some attributes could not be added.</returns>
        /// <exception cref="InvalidOperationException">All intrinsic callables need to have exactly one body specialization.</exception>
        public static bool TryAddMissingTargetInstructionAttributes(QsCompilation compilation, out QsCompilation transformed)
        {
            var           success          = true;
            List <string> instructionNames = new List <string>();

            // populate the intruction names with all manually specified ones first
            foreach (var callable in compilation.Namespaces.Callables())
            {
                var manuallySpecified = SymbolResolution.TryGetTargetInstructionName(callable.Attributes);
                if (manuallySpecified.IsValue)
                {
                    instructionNames.Add(manuallySpecified.Item);
                }
            }

            QsCallable AddAttribute(QsCallable callable)
            {
                if (callable.Specializations.Length != 1)
                {
                    throw new InvalidOperationException("intrinsic callable needs to have exactly one body specialization");
                }

                var instructionName = callable.FullName.Name.ToLowerInvariant();

                if (instructionNames.Contains(instructionName))
                {
                    success = false;
                    return(callable);
                }
                return(callable.AddAttribute(
                           AttributeUtils.BuildAttribute(
                               BuiltIn.TargetInstruction.FullName,
                               AttributeUtils.StringArgument(instructionName))));
            }

            QsNamespace AddAttributes(QsNamespace ns)
            {
                var elements = ns.Elements.Select(element =>
                                                  element is QsNamespaceElement.QsCallable callable &&
                                                  callable.Item.IsIntrinsic &&
                                                  callable.Item.Signature.TypeParameters.Length == 0 &&
                                                  !NameDecorator.IsAutoGeneratedName(callable.Item.FullName) &&
                                                  !callable.Item.Kind.IsTypeConstructor &&
                                                  !callable.Item.Attributes.Any(BuiltIn.DefinesTargetInstruction)
                    ? QsNamespaceElement.NewQsCallable(AddAttribute(callable.Item))
                    : element);

                return(new QsNamespace(ns.Name, elements.ToImmutableArray(), ns.Documentation));
            }

            var namespaces = compilation.Namespaces.Select(AddAttributes).ToImmutableArray();

            transformed = new QsCompilation(namespaces, compilation.EntryPoints);
            return(success);
        }
コード例 #5
0
 // TODO: Hack
 public void ResetSymbolTable()
 {
     SymbolTable = new SymbolTable(this);
     SymbolTable.DefineBuiltinPrimitives();
     // Load prelude
     {
         // TODO: Syntax status?
         var preludeAst = LoadAst("prelude.yk");
         // TODO: compile status?
         SymbolResolution.Resolve(SymbolTable, preludeAst);
     }
     SymbolTable.DefineBuiltinIntrinsics();
 }
コード例 #6
0
        private Expression MakePathExpression(params string[] pieces)
        {
            Debug.Assert(pieces.Length > 0);
            Expression result = new Expression.Identifier(null, pieces[0]);

            foreach (var piece in pieces.Skip(1))
            {
                result = new Expression.DotPath(null, result, piece);
            }
            // TODO: compile status?
            SymbolResolution.Resolve(SymbolTable, result);
            return(result);
        }
コード例 #7
0
ファイル: DocItem.cs プロジェクト: vxfield/qsharp-compiler
        /// <summary>
        /// Constructs a documented item.
        /// </summary>
        /// <param name="nsName">The name of the namespace that defines this item</param>
        /// <param name="itemName">The name of the item itself</param>
        /// <param name="kind">The item's kind: operation, function, or UDT</param>
        /// <param name="documentation">The source documentation for the item</param>
        internal DocItem(string nsName, string itemName, string kind, ImmutableArray <string> documentation,
                         IEnumerable <QsDeclarationAttribute> attributes)
        {
            namespaceName = nsName;
            name          = itemName;
            uid           = (namespaceName + "." + name).ToLowerInvariant();
            itemType      = kind;
            var res = SymbolResolution.TryFindRedirect(attributes);

            deprecated  = res.IsValue;
            replacement = res.ValueOr("");
            comments    = new DocComment(documentation, name, deprecated, replacement);
        }
コード例 #8
0
        public Declaration.File Elim(Declaration.File file)
        {
            var collector = new CollectDependencies(System);

            collector.Collect(file);
            dependencyMap = collector.DependencyMap;
            var result = (Declaration.File)Transform(file);

            System.ResetSymbolTable();
            // TODO: note below
            // NOTE: Do we need to care about compile status here?
            SymbolResolution.Resolve(System.SymbolTable, result);
            //Console.WriteLine(result.Dump());
            return(result);
        }
コード例 #9
0
        public DependencySystem(string standardLibraryPath)
        {
            StandardLibraryPath = standardLibraryPath;

            SymbolTable    = new SymbolTable(this);
            TypeTranslator = new TypeTranslator(this);
            codegen        = new Codegen(this);
            typeEval       = new TypeEval(this);
            typeCheck      = new TypeCheck(this);

            SymbolTable.DefineBuiltinPrimitives();
            // Load prelude
            {
                // TODO: syntax status?
                var preludeAst = LoadAst("prelude.yk");
                // TODO: compile status?
                SymbolResolution.Resolve(SymbolTable, preludeAst);
            }
            SymbolTable.DefineBuiltinIntrinsics();

            CompileError += OnCompileError;
        }
コード例 #10
0
        /// <summary>
        /// Returns a sequence of suggestions on how deprecated syntax can be updated based on the generated diagnostics,
        /// and given the file for which those diagnostics were generated.
        /// Returns an empty enumerable if any of the given arguments is null.
        /// </summary>
        internal static IEnumerable <(string, WorkspaceEdit)> SuggestionsForDeprecatedSyntax
            (this FileContentManager file, IEnumerable <Diagnostic> diagnostics)
        {
            if (file == null || diagnostics == null)
            {
                return(Enumerable.Empty <(string, WorkspaceEdit)>());
            }
            var deprecatedUnitTypes         = diagnostics.Where(DiagnosticTools.WarningType(WarningCode.DeprecatedUnitType));
            var deprecatedNOToperators      = diagnostics.Where(DiagnosticTools.WarningType(WarningCode.DeprecatedNOToperator));
            var deprecatedANDoperators      = diagnostics.Where(DiagnosticTools.WarningType(WarningCode.DeprecatedANDoperator));
            var deprecatedORoperators       = diagnostics.Where(DiagnosticTools.WarningType(WarningCode.DeprecatedORoperator));
            var deprecatedOpCharacteristics = diagnostics.Where(DiagnosticTools.WarningType(WarningCode.DeprecatedOpCharacteristics));

            (string, WorkspaceEdit) ReplaceWith(string text, LSP.Range range)
            {
                bool NeedsWs(Char ch) => Char.IsLetterOrDigit(ch) || ch == '_';

                if (range?.Start != null && range.End != null)
                {
                    var beforeEdit = file.GetLine(range.Start.Line).Text.Substring(0, range.Start.Character);
                    var afterEdit  = file.GetLine(range.End.Line).Text.Substring(range.End.Character);
                    if (beforeEdit.Any() && NeedsWs(beforeEdit.Last()))
                    {
                        text = $" {text}";
                    }
                    if (afterEdit.Any() && NeedsWs(afterEdit.First()))
                    {
                        text = $"{text} ";
                    }
                }
                var edit = new TextEdit {
                    Range = range?.Copy(), NewText = text
                };

                return($"Replace with \"{text.Trim()}\".", file.GetWorkspaceEdit(edit));
            }

            // update deprecated keywords and operators

            var suggestionsForUnitType = deprecatedUnitTypes.Select(d => ReplaceWith(Keywords.qsUnit.id, d.Range));
            var suggestionsForNOT      = deprecatedNOToperators.Select(d => ReplaceWith(Keywords.qsNOTop.op, d.Range));
            var suggestionsForAND      = deprecatedANDoperators.Select(d => ReplaceWith(Keywords.qsANDop.op, d.Range));
            var suggestionsForOR       = deprecatedORoperators.Select(d => ReplaceWith(Keywords.qsORop.op, d.Range));

            // update deprecated operation characteristics syntax

            var typeToQs = new ExpressionTypeToQs(new ExpressionToQs());

            string CharacteristicsAnnotation(Characteristics c)
            {
                typeToQs.onCharacteristicsExpression(SymbolResolution.ResolveCharacteristics(c));
                return($"{Keywords.qsCharacteristics.id} {typeToQs.Output}");
            }

            var suggestionsForOpCharacteristics = deprecatedOpCharacteristics.SelectMany(d =>
            {
                // TODO: TryGetQsSymbolInfo currently only returns information about the inner most leafs rather than all types etc.
                // Once it returns indeed all types in the fragment, the following code block should be replaced by the commented out code below.
                var fragment = file.TryGetFragmentAt(d.Range.Start, out var _);
                IEnumerable <Characteristics> GetCharacteristics(QsTuple <Tuple <QsSymbol, QsType> > argTuple) =>
                SyntaxGenerator.ExtractItems(argTuple).SelectMany(item => item.Item2.ExtractCharacteristics()).Distinct();
                var characteristicsInFragment =
                    fragment?.Kind is QsFragmentKind.FunctionDeclaration function ? GetCharacteristics(function.Item2.Argument) :
                    fragment?.Kind is QsFragmentKind.OperationDeclaration operation ? GetCharacteristics(operation.Item2.Argument) :
                    fragment?.Kind is QsFragmentKind.TypeDefinition type ? GetCharacteristics(type.Item2) :
                    Enumerable.Empty <Characteristics>();

                //var symbolInfo = file.TryGetQsSymbolInfo(d.Range.Start, false, out var fragment);
                //var characteristicsInFragment = (symbolInfo?.UsedTypes ?? Enumerable.Empty<QsType>())
                //    .SelectMany(t => t.ExtractCharacteristics()).Distinct();
                var fragmentStart = fragment?.GetRange()?.Start;
                return(characteristicsInFragment
                       .Where(c => c.Range.IsValue && DiagnosticTools.GetAbsoluteRange(fragmentStart, c.Range.Item).Overlaps(d.Range))
                       .Select(c => ReplaceWith(CharacteristicsAnnotation(c), d.Range)));
            });

            return(suggestionsForOpCharacteristics.ToArray()
                   .Concat(suggestionsForUnitType)
                   .Concat(suggestionsForNOT)
                   .Concat(suggestionsForAND)
                   .Concat(suggestionsForOR));
        }