private void ReplayVarUsage(LocalFunctionSymbol localFunc,
                                    SyntaxNode syntax,
                                    bool isWrite)
        {
            LocalFuncUsages usages = GetOrCreateLocalFuncUsages(localFunc);
            var state = isWrite ? usages.WrittenVars : usages.ReadVars;

            // Start at slot 1 (slot 0 just indicates reachability)
            for (int slot = 1; slot < state.Capacity; slot++)
            {
                if (state[slot])
                {
                    if (isWrite)
                    {
                        SetSlotAssigned(slot);
                    }
                    else
                    {
                        var symbol = variableBySlot[slot].Symbol;
                        CheckAssigned(symbol, syntax, slot);
                    }
                }
            }

            usages.LocalFuncVisited = true;
        }
        /// <summary>
        /// At the local function's use site, checks that all variables read
        /// are assigned and assigns all variables that are definitely assigned
        /// to be definitely assigned.
        /// </summary>
        private void ReplayReadsAndWrites(LocalFunctionSymbol localFunc,
                                          SyntaxNode syntax,
                                          bool writes)
        {
            _usedLocalFunctions.Add(localFunc);

            // First process the reads
            ReplayVarUsage(localFunc,
                           syntax,
                           isWrite: false);

            // Now the writes
            if (writes)
            {
                ReplayVarUsage(localFunc,
                               syntax,
                               isWrite: true);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// At the local function's use site, checks that all variables read
        /// are assigned and assigns all variables that are definitely assigned
        /// to be definitely assigned.
        /// </summary>
        private void ReplayReadsAndWrites(LocalFunctionSymbol localFunc,
                                          SyntaxNode syntax,
                                          bool writes)
        {
            _usedLocalFunctions.Add(localFunc);

            var usages = GetOrCreateLocalFuncUsages(localFunc);

            // First process the reads
            ReplayReads(ref usages.ReadVars, syntax);

            // Now the writes
            if (writes)
            {
                UnionWith(ref this.State, ref usages.WrittenVars);
            }

            usages.LocalFuncVisited = true;
        }
Ejemplo n.º 4
0
        private BoundStatement BindLocalFunctionStatementParts(LocalFunctionStatementSyntax node, DiagnosticBag diagnostics)
        {
            // already defined symbol in containing block
            var localSymbol = this.LookupLocalFunction(node.Identifier);

            var hasErrors = false;

            // In error scenarios with misplaced code, it is possible we can't bind the local declaration.
            // This occurs through the semantic model.  In that case concoct a plausible result.
            if (localSymbol == null)
            {
                localSymbol = new LocalFunctionSymbol(this, this.ContainingMemberOrLambda, node);
            }
            else
            {
                hasErrors |= this.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics);
            }

            BoundBlock block;
            if (node.Body != null)
            {
                block = BindEmbeddedBlock(node.Body, diagnostics);
            }
            else if (node.ExpressionBody != null)
            {
                block = BindExpressionBodyAsBlock(node.ExpressionBody, diagnostics);
            }
            else
            {
                block = null;
                hasErrors = true;
                // TODO: add a message for this?
                diagnostics.Add(ErrorCode.ERR_ConcreteMissingBody, localSymbol.Locations[0], localSymbol);
            }

            if (block != null)
            {
                localSymbol.ComputeReturnType();

                // Have to do ControlFlowPass here because in MethodCompiler, we don't call this for synthed methods
                // rather we go directly to LowerBodyOrInitializer, which skips over flow analysis (which is in CompileMethod)
                // (the same thing - calling ControlFlowPass.Analyze in the lowering - is done for lambdas)
                // It's a bit of code duplication, but refactoring would make things worse.
                var endIsReachable = ControlFlowPass.Analyze(localSymbol.DeclaringCompilation, localSymbol, block, diagnostics);
                if (endIsReachable)
                {
                    if (ImplicitReturnIsOkay(localSymbol))
                    {
                        block = FlowAnalysisPass.AppendImplicitReturn(block, localSymbol, node.Body);
                    }
                    else
                    {
                        diagnostics.Add(ErrorCode.ERR_ReturnExpected, localSymbol.Locations[0], localSymbol);
                    }
                }
            }

            localSymbol.GrabDiagnostics(diagnostics);

            return new BoundLocalFunctionStatement(node, localSymbol, block, hasErrors);
        }
Ejemplo n.º 5
0
 public LocalFunctionTypeParameterSymbol(LocalFunctionSymbol owner, string name, int ordinal, ImmutableArray<Location> locations, ImmutableArray<SyntaxReference> syntaxRefs)
     : base(name, ordinal, locations, syntaxRefs)
 {
     _owner = owner;
 }
 private LocalFuncUsages GetOrCreateLocalFuncUsages(LocalFunctionSymbol localFunc)
 {
     LocalFuncUsages usages;
     if (!_localFuncVarUsages.TryGetValue(localFunc, out usages))
     {
         usages = new LocalFuncUsages();
         _localFuncVarUsages[localFunc] = usages;
     }
     return usages;
 }
Ejemplo n.º 7
0
 private LocalFuncUsages GetOrCreateLocalFuncUsages(LocalFunctionSymbol localFunc)
 {
     LocalFuncUsages usages;
     if (!_localFuncVarUsages.TryGetValue(localFunc, out usages))
     {
         usages = _localFuncVarUsages[localFunc] = new LocalFuncUsages(UnreachableState());
     }
     return usages;
 }