public override BoundNode VisitHostObjectMemberReference(BoundHostObjectMemberReference node) { Debug.Assert(previousSubmissionFields != null); Debug.Assert(!containingSymbol.IsStatic); var hostObjectReference = previousSubmissionFields.GetHostObjectField(); var thisReference = new BoundThisReference(null, null, containingSymbol.ThisParameter, containingType); return new BoundFieldAccess(null, null, thisReference, hostObjectReference, constantValueOpt: null); }
public override BoundNode VisitPreviousSubmissionReference(BoundPreviousSubmissionReference node) { var targetType = (ImplicitTypeSymbol)node.Type; Debug.Assert(targetType.IsScriptClass); Debug.Assert(!containingSymbol.IsStatic); Debug.Assert(previousSubmissionFields != null); var targetScriptReference = previousSubmissionFields.GetOrMakeField(targetType); var thisReference = new BoundThisReference(null, null, containingSymbol.ThisParameter, containingType); return new BoundFieldAccess(null, null, thisReference, targetScriptReference, constantValueOpt: null); }
/// <summary> /// In embedded statements, returns a BoundLocal when the type was explicit. /// In global statements, returns a BoundFieldAccess when the type was explicit. /// Otherwise returns a DeconstructionVariablePendingInference when the type is implicit. /// </summary> private BoundExpression BindDeconstructionVariable( TypeSymbol declType, SingleVariableDesignationSyntax designation, DiagnosticBag diagnostics) { SourceLocalSymbol localSymbol = LookupLocal(designation.Identifier); // is this a local? if ((object)localSymbol != null) { // Check for variable declaration errors. // Use the binder that owns the scope for the local because this (the current) binder // might own nested scope. var hasErrors = localSymbol.ScopeBinder.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics); if ((object)declType != null) { return(new BoundLocal(designation, localSymbol, isDeclaration: true, constantValueOpt: null, type: declType, hasErrors: hasErrors)); } return(new DeconstructionVariablePendingInference(designation, localSymbol, receiverOpt: null)); } // Is this a field? GlobalExpressionVariable field = LookupDeclaredField(designation); if ((object)field == null) { // We should have the right binder in the chain, cannot continue otherwise. throw ExceptionUtilities.Unreachable; } BoundThisReference receiver = ThisReference(designation, this.ContainingType, hasErrors: false, wasCompilerGenerated: true); if ((object)declType != null) { TypeSymbol fieldType = field.GetFieldType(this.FieldsBeingBound); Debug.Assert(declType == fieldType); return(new BoundFieldAccess(designation, receiver, field, constantValueOpt: null, resultKind: LookupResultKind.Viable, type: fieldType)); } return(new DeconstructionVariablePendingInference(designation, field, receiver)); }
/// <summary> /// Construct a body for an auto-property accessor (updating or returning the backing field). /// </summary> internal static BoundBlock ConstructAutoPropertyAccessorBody(SourceMemberMethodSymbol accessor) { Debug.Assert(accessor.MethodKind == MethodKind.PropertyGet || accessor.MethodKind == MethodKind.PropertySet); var property = (SourcePropertySymbol)accessor.AssociatedSymbol; CSharpSyntaxNode syntax = property.CSharpSyntaxNode; BoundExpression thisReference = null; if (!accessor.IsStatic) { var thisSymbol = accessor.ThisParameter; thisReference = new BoundThisReference(syntax, thisSymbol.Type.TypeSymbol) { WasCompilerGenerated = true }; } var field = property.BackingField; var fieldAccess = new BoundFieldAccess(syntax, thisReference, field, ConstantValue.NotAvailable) { WasCompilerGenerated = true }; BoundStatement statement; if (accessor.MethodKind == MethodKind.PropertyGet) { statement = new BoundReturnStatement(accessor.SyntaxNode, RefKind.None, fieldAccess); } else { Debug.Assert(accessor.MethodKind == MethodKind.PropertySet); var parameter = accessor.Parameters[0]; statement = new BoundExpressionStatement( accessor.SyntaxNode, new BoundAssignmentOperator( syntax, fieldAccess, new BoundParameter(syntax, parameter) { WasCompilerGenerated = true }, property.Type.TypeSymbol) { WasCompilerGenerated = true }); } return(BoundBlock.SynthesizedNoLocals(syntax, statement)); }
public override BoundNode VisitPreviousSubmissionReference(BoundPreviousSubmissionReference node) { var targetType = (ImplicitNamedTypeSymbol)node.Type; Debug.Assert(targetType.TypeKind == TypeKind.Submission); Debug.Assert(!_factory.TopLevelMethod.IsStatic); Debug.Assert(_previousSubmissionFields != null); var syntax = node.Syntax; var targetScriptReference = _previousSubmissionFields.GetOrMakeField(targetType); var thisReference = new BoundThisReference(syntax, _factory.CurrentType); return(new BoundFieldAccess(syntax, thisReference, targetScriptReference, ConstantValue.NotAvailable)); }
public override BoundNode VisitThisReference(BoundThisReference node) { // "topLevelMethod.ThisParameter == null" can occur in a delegate creation expression because the method group // in the argument can have a "this" receiver even when "this" // is not captured because a static method is selected. But we do preserve // the method group and its receiver in the bound tree. // No need to capture "this" in such case. // TODO: Why don't we drop "this" while lowering if method is static? // Actually, considering that method group expression does not evaluate to a particular value // why do we have it in the lowered tree at all? return(currentMethod == topLevelMethod || topLevelMethod.ThisParameter == null ? node : FramePointer(node.Syntax, (NamedTypeSymbol)node.Type)); }
public override BoundNode VisitThisReference(BoundThisReference node) { var thisParam = _topLevelMethod.ThisParameter; if (thisParam != null) { ReferenceVariable(node.Syntax, thisParam); } else { // This can occur in a delegate creation expression because the method group // in the argument can have a "this" receiver even when "this" // is not captured because a static method is selected. But we do preserve // the method group and its receiver in the bound tree. // No need to capture "this" in such case. // TODO: Why don't we drop "this" while lowering if method is static? // Actually, considering that method group expression does not evaluate to a particular value // why do we have it in the lowered tree at all? } return(base.VisitThisReference(node)); }
public override BoundNode VisitThisReference(BoundThisReference node) { return(RewriteParameter(node.Syntax, _targetMethodThisParameter, node)); }
private EEMethodSymbol GetThisMethod(EENamedTypeSymbol container, string methodName) { var syntax = SyntaxFactory.ThisExpression(); return this.CreateMethod(container, methodName, syntax, (method, diagnostics) => { var expression = new BoundThisReference(syntax, GetNonDisplayClassContainer(container.SubstitutedSourceType)); return new BoundReturnStatement(syntax, expression) { WasCompilerGenerated = true }; }); }
public override BoundNode VisitThisReference(BoundThisReference node) { return RewriteParameter(node.Syntax, _targetMethodThisParameter, node); }
public override object VisitThisReference(BoundThisReference node, object arg) { // TODO: in a struct constructor, "this" is not initially assigned. CheckAssigned(ThisSymbol, node.Syntax); return(null); }
internal static ImmutableArray <BoundStatement> ConstructScriptConstructorBody( BoundStatement loweredBody, MethodSymbol constructor, SynthesizedSubmissionFields previousSubmissionFields, CSharpCompilation compilation ) { // Script field initializers have to be emitted after the call to the base constructor because they can refer to "this" instance. // // Unlike regular field initializers, initializers of global script variables can access "this" instance. // If the base class had a constructor that initializes its state a global variable would access partially initialized object. // For this reason Script class must always derive directly from a class that has no state (System.Object). SyntaxNode syntax = loweredBody.Syntax; // base constructor call: Debug.Assert( (object)constructor.ContainingType.BaseTypeNoUseSiteDiagnostics == null || constructor.ContainingType.BaseTypeNoUseSiteDiagnostics.SpecialType == SpecialType.System_Object ); var objectType = constructor.ContainingAssembly.GetSpecialType( SpecialType.System_Object ); BoundExpression receiver = new BoundThisReference(syntax, constructor.ContainingType) { WasCompilerGenerated = true }; BoundStatement baseConstructorCall = new BoundExpressionStatement( syntax, new BoundCall( syntax, receiverOpt: receiver, method: objectType.InstanceConstructors[0], arguments: ImmutableArray <BoundExpression> .Empty, argumentNamesOpt: ImmutableArray <string> .Empty, argumentRefKindsOpt: ImmutableArray <RefKind> .Empty, isDelegateCall: false, expanded: false, invokedAsExtensionMethod: false, argsToParamsOpt: ImmutableArray <int> .Empty, defaultArguments: BitVector.Empty, resultKind: LookupResultKind.Viable, type: objectType ) { WasCompilerGenerated = true } ) { WasCompilerGenerated = true }; var statements = ArrayBuilder <BoundStatement> .GetInstance(); statements.Add(baseConstructorCall); if (constructor.IsSubmissionConstructor) { // submission initialization: MakeSubmissionInitialization( statements, syntax, constructor, previousSubmissionFields, compilation ); } statements.Add(loweredBody); return(statements.ToImmutableAndFree()); }
/// <summary> /// Generate a thread-safe accessor for a regular field-like event. /// /// DelegateType tmp0 = _event; //backing field /// DelegateType tmp1; /// DelegateType tmp2; /// do { /// tmp1 = tmp0; /// tmp2 = (DelegateType)Delegate.Combine(tmp1, value); //Remove for -= /// tmp0 = Interlocked.CompareExchange<DelegateType>(ref _event, tmp2, tmp1); /// } while ((object)tmp0 != (object)tmp1); /// /// Note, if System.Threading.Interlocked.CompareExchange<T> is not available, /// we emit the following code and mark the method Synchronized (unless it is a struct). /// /// _event = (DelegateType)Delegate.Combine(_event, value); //Remove for -= /// /// </summary> internal static BoundBlock ConstructFieldLikeEventAccessorBody_Regular(SourceEventSymbol eventSymbol, bool isAddMethod, CSharpCompilation compilation, DiagnosticBag diagnostics) { CSharpSyntaxNode syntax = eventSymbol.CSharpSyntaxNode; TypeSymbol delegateType = eventSymbol.Type; MethodSymbol accessor = isAddMethod ? eventSymbol.AddMethod : eventSymbol.RemoveMethod; ParameterSymbol thisParameter = accessor.ThisParameter; TypeSymbol boolType = compilation.GetSpecialType(SpecialType.System_Boolean); SpecialMember updateMethodId = isAddMethod ? SpecialMember.System_Delegate__Combine : SpecialMember.System_Delegate__Remove; MethodSymbol updateMethod = (MethodSymbol)compilation.GetSpecialTypeMember(updateMethodId); BoundStatement @return = new BoundReturnStatement(syntax, expressionOpt: null) { WasCompilerGenerated = true }; if (updateMethod == null) { MemberDescriptor memberDescriptor = SpecialMembers.GetDescriptor(updateMethodId); diagnostics.Add(new CSDiagnostic(new CSDiagnosticInfo(ErrorCode.ERR_MissingPredefinedMember, memberDescriptor.DeclaringTypeMetadataName, memberDescriptor.Name), syntax.Location)); return(new BoundBlock(syntax, locals: ImmutableArray <LocalSymbol> .Empty, statements: ImmutableArray.Create <BoundStatement>(@return)) { WasCompilerGenerated = true }); } Binder.ReportUseSiteDiagnostics(updateMethod, diagnostics, syntax); BoundThisReference fieldReceiver = eventSymbol.IsStatic ? null : new BoundThisReference(syntax, thisParameter.Type) { WasCompilerGenerated = true }; BoundFieldAccess boundBackingField = new BoundFieldAccess(syntax, receiver: fieldReceiver, fieldSymbol: eventSymbol.AssociatedField, constantValueOpt: null) { WasCompilerGenerated = true }; BoundParameter boundParameter = new BoundParameter(syntax, parameterSymbol: accessor.Parameters[0]) { WasCompilerGenerated = true }; BoundExpression delegateUpdate; MethodSymbol compareExchangeMethod = (MethodSymbol)compilation.GetWellKnownTypeMember(WellKnownMember.System_Threading_Interlocked__CompareExchange_T); if ((object)compareExchangeMethod == null) { // (DelegateType)Delegate.Combine(_event, value) delegateUpdate = BoundConversion.SynthesizedNonUserDefined(syntax, operand: BoundCall.Synthesized(syntax, receiverOpt: null, method: updateMethod, arguments: ImmutableArray.Create <BoundExpression>(boundBackingField, boundParameter)), kind: ConversionKind.ExplicitReference, type: delegateType); // _event = (DelegateType)Delegate.Combine(_event, value); BoundStatement eventUpdate = new BoundExpressionStatement(syntax, expression: new BoundAssignmentOperator(syntax, left: boundBackingField, right: delegateUpdate, type: delegateType) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }; return(new BoundBlock(syntax, locals: ImmutableArray <LocalSymbol> .Empty, statements: ImmutableArray.Create <BoundStatement>( eventUpdate, @return)) { WasCompilerGenerated = true }); } compareExchangeMethod = compareExchangeMethod.Construct(ImmutableArray.Create <TypeSymbol>(delegateType)); Binder.ReportUseSiteDiagnostics(compareExchangeMethod, diagnostics, syntax); GeneratedLabelSymbol loopLabel = new GeneratedLabelSymbol("loop"); const int numTemps = 3; LocalSymbol[] tmps = new LocalSymbol[numTemps]; BoundLocal[] boundTmps = new BoundLocal[numTemps]; for (int i = 0; i < numTemps; i++) { tmps[i] = new SynthesizedLocal(accessor, delegateType, SynthesizedLocalKind.LoweringTemp); boundTmps[i] = new BoundLocal(syntax, tmps[i], null, delegateType); } // tmp0 = _event; BoundStatement tmp0Init = new BoundExpressionStatement(syntax, expression: new BoundAssignmentOperator(syntax, left: boundTmps[0], right: boundBackingField, type: delegateType) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }; // LOOP: BoundStatement loopStart = new BoundLabelStatement(syntax, label: loopLabel) { WasCompilerGenerated = true }; // tmp1 = tmp0; BoundStatement tmp1Update = new BoundExpressionStatement(syntax, expression: new BoundAssignmentOperator(syntax, left: boundTmps[1], right: boundTmps[0], type: delegateType) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }; // (DelegateType)Delegate.Combine(tmp1, value) delegateUpdate = BoundConversion.SynthesizedNonUserDefined(syntax, operand: BoundCall.Synthesized(syntax, receiverOpt: null, method: updateMethod, arguments: ImmutableArray.Create <BoundExpression>(boundTmps[1], boundParameter)), kind: ConversionKind.ExplicitReference, type: delegateType); // tmp2 = (DelegateType)Delegate.Combine(tmp1, value); BoundStatement tmp2Update = new BoundExpressionStatement(syntax, expression: new BoundAssignmentOperator(syntax, left: boundTmps[2], right: delegateUpdate, type: delegateType) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }; // Interlocked.CompareExchange<DelegateType>(ref _event, tmp2, tmp1) BoundExpression compareExchange = BoundCall.Synthesized(syntax, receiverOpt: null, method: compareExchangeMethod, arguments: ImmutableArray.Create <BoundExpression>(boundBackingField, boundTmps[2], boundTmps[1])); // tmp0 = Interlocked.CompareExchange<DelegateType>(ref _event, tmp2, tmp1); BoundStatement tmp0Update = new BoundExpressionStatement(syntax, expression: new BoundAssignmentOperator(syntax, left: boundTmps[0], right: compareExchange, type: delegateType) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }; // tmp0 == tmp1 // i.e. exit when they are equal, jump to start otherwise BoundExpression loopExitCondition = new BoundBinaryOperator(syntax, operatorKind: BinaryOperatorKind.ObjectEqual, left: boundTmps[0], right: boundTmps[1], constantValueOpt: null, methodOpt: null, resultKind: LookupResultKind.Viable, type: boolType) { WasCompilerGenerated = true }; // branchfalse (tmp0 == tmp1) LOOP BoundStatement loopEnd = new BoundConditionalGoto(syntax, condition: loopExitCondition, jumpIfTrue: false, label: loopLabel) { WasCompilerGenerated = true }; return(new BoundBlock(syntax, locals: tmps.AsImmutable(), statements: ImmutableArray.Create <BoundStatement>( tmp0Init, loopStart, tmp1Update, tmp2Update, tmp0Update, loopEnd, @return)) { WasCompilerGenerated = true }); }
public override BoundNode VisitThisReference(BoundThisReference node) { variablesCaptured.Add(topLevelMethod.ThisParameter, node.Syntax); return(base.VisitThisReference(node)); }
private void EmitThisStore(BoundThisReference thisRef) { Debug.Assert(thisRef.Type.IsValueType); _builder.EmitOpCode(ILOpCode.Stobj); EmitSymbolToken(thisRef.Type, thisRef.Syntax); }
internal void Parse(BoundThisReference boundThisReference) { base.Parse(boundThisReference); }
/// <summary> /// Generates a submission initialization part of a Script type constructor that represents an interactive submission. /// </summary> /// <remarks> /// The constructor takes a parameter of type Roslyn.Scripting.Session - the session reference. /// It adds the object being constructed into the session by calling Microsoft.CSharp.RuntimeHelpers.SessionHelpers.SetSubmission, /// and retrieves strongly typed references on all previous submission script classes whose members are referenced by this submission. /// The references are stored to fields of the submission (<paramref name="synthesizedFields"/>). /// </remarks> private static ImmutableArray <BoundStatement> MakeSubmissionInitialization(CSharpSyntaxNode syntax, MethodSymbol submissionConstructor, SynthesizedSubmissionFields synthesizedFields, CSharpCompilation compilation) { Debug.Assert(submissionConstructor.ParameterCount == 2); BoundStatement[] result = new BoundStatement[1 + synthesizedFields.Count]; var sessionReference = new BoundParameter(syntax, submissionConstructor.Parameters[0]) { WasCompilerGenerated = true }; var submissionGetter = (MethodSymbol)compilation.GetWellKnownTypeMember( WellKnownMember.Microsoft_CSharp_RuntimeHelpers_SessionHelpers__GetSubmission ); var submissionAdder = (MethodSymbol)compilation.GetWellKnownTypeMember( WellKnownMember.Microsoft_CSharp_RuntimeHelpers_SessionHelpers__SetSubmission ); // TODO: report missing adder/getter Debug.Assert((object)submissionAdder != null && (object)submissionGetter != null); var intType = compilation.GetSpecialType(SpecialType.System_Int32); var thisReference = new BoundThisReference(syntax, submissionConstructor.ContainingType) { WasCompilerGenerated = true }; int i = 0; // hostObject = (THostObject)SessionHelpers.SetSubmission(<session>, <slot index>, this); var slotIndex = compilation.GetSubmissionSlotIndex(); Debug.Assert(slotIndex >= 0); BoundExpression setSubmission = BoundCall.Synthesized(syntax, null, submissionAdder, sessionReference, new BoundLiteral(syntax, ConstantValue.Create(slotIndex), intType) { WasCompilerGenerated = true }, thisReference ); var hostObjectField = synthesizedFields.GetHostObjectField(); if ((object)hostObjectField != null) { setSubmission = new BoundAssignmentOperator(syntax, new BoundFieldAccess(syntax, thisReference, hostObjectField, ConstantValue.NotAvailable) { WasCompilerGenerated = true }, BoundConversion.Synthesized(syntax, setSubmission, Conversion.ExplicitReference, false, true, ConstantValue.NotAvailable, hostObjectField.Type ), hostObjectField.Type ) { WasCompilerGenerated = true }; } result[i++] = new BoundExpressionStatement(syntax, setSubmission) { WasCompilerGenerated = true }; foreach (var field in synthesizedFields.FieldSymbols) { var targetScriptClass = (ImplicitNamedTypeSymbol)field.Type; var targetSubmissionId = targetScriptClass.DeclaringCompilation.GetSubmissionSlotIndex(); Debug.Assert(targetSubmissionId >= 0); // this.<field> = (<FieldType>)SessionHelpers.GetSubmission(<session>, <i>); result[i++] = new BoundExpressionStatement(syntax, new BoundAssignmentOperator(syntax, new BoundFieldAccess(syntax, thisReference, field, ConstantValue.NotAvailable) { WasCompilerGenerated = true }, BoundConversion.Synthesized(syntax, BoundCall.Synthesized(syntax, null, submissionGetter, sessionReference, new BoundLiteral(syntax, ConstantValue.Create(targetSubmissionId), intType) { WasCompilerGenerated = true }), Conversion.ExplicitReference, false, true, ConstantValue.NotAvailable, targetScriptClass ), targetScriptClass ) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }; } Debug.Assert(i == result.Length); return(result.AsImmutableOrNull()); }
public override BoundNode VisitThisReference(BoundThisReference node) { CheckReferenceToThisOrBase(node); return(base.VisitThisReference(node)); }
private EEMethodSymbol GetThisMethod(EENamedTypeSymbol container, string methodName) { var syntax = SyntaxFactory.ThisExpression(); return this.CreateMethod(container, methodName, syntax, (EEMethodSymbol method, DiagnosticBag diagnostics, out ImmutableArray<LocalSymbol> declaredLocals) => { declaredLocals = ImmutableArray<LocalSymbol>.Empty; var expression = new BoundThisReference(syntax, GetNonDisplayClassContainer(container.SubstitutedSourceType)); return new BoundReturnStatement(syntax, RefKind.None, expression) { WasCompilerGenerated = true }; }); }
private void EmitThisReferenceExpression(BoundThisReference thisRef) { var thisType = thisRef.Type; Debug.Assert(thisType.TypeKind != TypeKind.TypeParameter); _builder.EmitOpCode(ILOpCode.Ldarg_0); if (thisType.IsValueType) { EmitLoadIndirect(thisType, thisRef.Syntax); } }
/// <summary> /// In embedded statements, returns a BoundLocal when the type was explicit. /// In global statements, returns a BoundFieldAccess when the type was explicit. /// Otherwise returns a DeconstructionVariablePendingInference when the type is implicit. /// </summary> private BoundExpression BindDeconstructionDeclarationVariable( TypeSyntax typeSyntax, SingleVariableDesignationSyntax designation, DiagnosticBag diagnostics) { SourceLocalSymbol localSymbol = LookupLocal(designation.Identifier); bool hasErrors = false; bool isVar; bool isConst = false; AliasSymbol alias; TypeSymbol declType = BindVariableType(designation, diagnostics, typeSyntax, ref isConst, out isVar, out alias); if (!isVar) { if (designation.Parent.Kind() == SyntaxKind.ParenthesizedVariableDesignation) { // An explicit type can only be provided next to the variable Error(diagnostics, ErrorCode.ERR_DeconstructionVarFormDisallowsSpecificType, designation); hasErrors = true; } } // is this a local? if (localSymbol != null) { // Check for variable declaration errors. // Use the binder that owns the scope for the local because this (the current) binder // might own nested scope. hasErrors |= localSymbol.ScopeBinder.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics); if (!isVar) { return(new BoundLocal(designation, localSymbol, constantValueOpt: null, type: declType, hasErrors: hasErrors)); } return(new DeconstructionVariablePendingInference(designation, localSymbol, receiverOpt: null)); } // Is this a field? GlobalExpressionVariable field = LookupDeclaredField(designation); if ((object)field == null) { // We should have the right binder in the chain, cannot continue otherwise. throw ExceptionUtilities.Unreachable; } BoundThisReference receiver = ThisReference(designation, this.ContainingType, hasErrors: false, wasCompilerGenerated: true); if (!isVar) { TypeSymbol fieldType = field.GetFieldType(this.FieldsBeingBound); return(new BoundFieldAccess(designation, receiver, field, constantValueOpt: null, resultKind: LookupResultKind.Viable, type: fieldType, hasErrors: hasErrors)); } return(new DeconstructionVariablePendingInference(designation, field, receiver)); }
public override BoundNode VisitThisReference(BoundThisReference node) { Capture(this.topLevelMethod.ThisParameter, node.Syntax); return(base.VisitThisReference(node)); }
internal static BoundCall GenerateObjectConstructorInitializer(MethodSymbol constructor, DiagnosticBag diagnostics) { NamedTypeSymbol objectType = constructor.ContainingType.BaseTypeNoUseSiteDiagnostics; Debug.Assert(objectType.SpecialType == SpecialType.System_Object); MethodSymbol objectConstructor = null; LookupResultKind resultKind = LookupResultKind.Viable; foreach (MethodSymbol objectCtor in objectType.InstanceConstructors) { if (objectCtor.ParameterCount == 0) { objectConstructor = objectCtor; break; } } // UNDONE: If this happens then something is deeply wrong. Should we give a better error? if ((object)objectConstructor == null) { diagnostics.Add(ErrorCode.ERR_BadCtorArgCount, constructor.Locations[0], objectType, /*desired param count*/ 0); return(null); } // UNDONE: If this happens then something is deeply wrong. Should we give a better error? bool hasErrors = false; HashSet <DiagnosticInfo> useSiteDiagnostics = null; if (!AccessCheck.IsSymbolAccessible(objectConstructor, constructor.ContainingType, ref useSiteDiagnostics)) { diagnostics.Add(ErrorCode.ERR_BadAccess, constructor.Locations[0], objectConstructor); resultKind = LookupResultKind.Inaccessible; hasErrors = true; } if (!useSiteDiagnostics.IsNullOrEmpty()) { diagnostics.Add(constructor.Locations.IsEmpty ? NoLocation.Singleton : constructor.Locations[0], useSiteDiagnostics); } CSharpSyntaxNode syntax = constructor.GetNonNullSyntaxNode(); BoundExpression receiver = new BoundThisReference(syntax, constructor.ContainingType) { WasCompilerGenerated = true }; return(new BoundCall( syntax: syntax, receiverOpt: receiver, method: objectConstructor, arguments: ImmutableArray <BoundExpression> .Empty, argumentNamesOpt: ImmutableArray <string> .Empty, argumentRefKindsOpt: ImmutableArray <RefKind> .Empty, isDelegateCall: false, expanded: false, invokedAsExtensionMethod: false, argsToParamsOpt: ImmutableArray <int> .Empty, resultKind: resultKind, type: objectType, hasErrors: hasErrors) { WasCompilerGenerated = true }); }
/// <summary> /// Generates a submission initialization part of a Script type constructor that represents an interactive submission. /// </summary> /// <remarks> /// The constructor takes a parameter of type Roslyn.Scripting.Session - the session reference. /// It adds the object being constructed into the session by calling Microsoft.CSharp.RuntimeHelpers.SessionHelpers.SetSubmission, /// and retrieves strongly typed references on all previous submission script classes whose members are referenced by this submission. /// The references are stored to fields of the submission (<paramref name="synthesizedFields"/>). /// </remarks> private static ImmutableArray <BoundStatement> MakeSubmissionInitialization(CSharpSyntaxNode syntax, MethodSymbol submissionConstructor, SynthesizedSubmissionFields synthesizedFields, CSharpCompilation compilation) { Debug.Assert(submissionConstructor.ParameterCount == 2); var statements = new List <BoundStatement>(2 + synthesizedFields.Count); var submissionArrayReference = new BoundParameter(syntax, submissionConstructor.Parameters[0]) { WasCompilerGenerated = true }; var intType = compilation.GetSpecialType(SpecialType.System_Int32); var objectType = compilation.GetSpecialType(SpecialType.System_Object); var thisReference = new BoundThisReference(syntax, submissionConstructor.ContainingType) { WasCompilerGenerated = true }; var slotIndex = compilation.GetSubmissionSlotIndex(); Debug.Assert(slotIndex >= 0); // <submission_array>[<slot_index] = this; statements.Add(new BoundExpressionStatement(syntax, new BoundAssignmentOperator(syntax, new BoundArrayAccess(syntax, submissionArrayReference, ImmutableArray.Create <BoundExpression>(new BoundLiteral(syntax, ConstantValue.Create(slotIndex), intType) { WasCompilerGenerated = true }), objectType) { WasCompilerGenerated = true }, thisReference, RefKind.None, thisReference.Type) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }); var hostObjectField = synthesizedFields.GetHostObjectField(); if ((object)hostObjectField != null) { // <host_object> = (<host_object_type>)<submission_array>[0] statements.Add( new BoundExpressionStatement(syntax, new BoundAssignmentOperator(syntax, new BoundFieldAccess(syntax, thisReference, hostObjectField, ConstantValue.NotAvailable) { WasCompilerGenerated = true }, BoundConversion.Synthesized(syntax, new BoundArrayAccess(syntax, submissionArrayReference, ImmutableArray.Create <BoundExpression>(new BoundLiteral(syntax, ConstantValue.Create(0), intType) { WasCompilerGenerated = true }), objectType), Conversion.ExplicitReference, false, true, ConstantValue.NotAvailable, hostObjectField.Type ), hostObjectField.Type) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }); } foreach (var field in synthesizedFields.FieldSymbols) { var targetScriptType = (ImplicitNamedTypeSymbol)field.Type; var targetSubmissionIndex = targetScriptType.DeclaringCompilation.GetSubmissionSlotIndex(); Debug.Assert(targetSubmissionIndex >= 0); // this.<field> = (<target_script_type>)<submission_array>[<target_submission_index>]; statements.Add( new BoundExpressionStatement(syntax, new BoundAssignmentOperator(syntax, new BoundFieldAccess(syntax, thisReference, field, ConstantValue.NotAvailable) { WasCompilerGenerated = true }, BoundConversion.Synthesized(syntax, new BoundArrayAccess(syntax, submissionArrayReference, ImmutableArray.Create <BoundExpression>(new BoundLiteral(syntax, ConstantValue.Create(targetSubmissionIndex), intType) { WasCompilerGenerated = true }), objectType) { WasCompilerGenerated = true }, Conversion.ExplicitReference, false, true, ConstantValue.NotAvailable, targetScriptType ), targetScriptType ) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }); } return(statements.AsImmutableOrNull()); }
public override BoundNode VisitThisReference(BoundThisReference node) { var rewrittenThis = GenerateThisReference(node); Debug.Assert(rewrittenThis.Type.Equals(node.Type, TypeCompareKind.IgnoreDynamicAndTupleNames)); return rewrittenThis; }