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); } }
/// <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; }
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); }
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; }
private LocalFuncUsages GetOrCreateLocalFuncUsages(LocalFunctionSymbol localFunc) { LocalFuncUsages usages; if (!_localFuncVarUsages.TryGetValue(localFunc, out usages)) { usages = _localFuncVarUsages[localFunc] = new LocalFuncUsages(UnreachableState()); } return usages; }