internal override AssignmentCallback EmitSet(CodeGenerator/*!*/ codeGenerator, IPlace instance, bool isRef, ConstructedType constructedType, bool runtimeVisibilityCheck) { return codeGenerator.EmitSetStaticPropertyOperator(declaringType, this.FullName, null, isRef); }
internal override AssignmentCallback EmitSet(CodeGenerator/*!*/ codeGenerator, IPlace instance, bool isRef, ConstructedType constructedType, bool runtimeVisibilityCheck) { Debug.Assert(IsStatic == (instance == null)); //Debug.Assert(hasSetter, "TODO"); if (!hasSetter) { throw new CompilerException( new ErrorInfo( 0, "readonly_property_written", ErrorSeverity.Error), new string[]{DeclaringType.FullName, this.Name.Value} ); } // if (IsStatic) { // check the visibility at runtime by the operator: if (runtimeVisibilityCheck) return codeGenerator.EmitSetStaticPropertyOperator(DeclaringType, this.FullName, null, isRef); } else { // load target instance: instance.EmitLoad(codeGenerator.IL); } return delegate(CodeGenerator codeGen, PhpTypeCode stackTypeCode) { MethodInfo setter = this.Setter; // TODO: can we get different PhpTypeCode? ILEmitter il = codeGen.IL; PropertyDesc.EmitSetConversion(il, stackTypeCode, setter.GetParameters()[0].ParameterType); il.Emit(setter.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, setter); }; }
internal override AssignmentCallback EmitSet(CodeGenerator/*!*/ codeGenerator, IPlace instance, bool isRef, ConstructedType constructedType, bool runtimeVisibilityCheck) { Debug.Assert(IsStatic == (instance == null)); if (IsStatic) { // check the visibility at runtime by the operator: if (runtimeVisibilityCheck) return codeGenerator.EmitSetStaticPropertyOperator(DeclaringType, this.FullName, null, isRef); } else { // load target instance: instance.EmitLoad(codeGenerator.IL); } return delegate(CodeGenerator codeGen, PhpTypeCode stackTypeCode) { // TODO: can we get different PhpTypeCode? ILEmitter il = codeGen.IL; PropertyDesc.EmitSetConversion(il, stackTypeCode, fieldInfo.FieldType); il.Emit(IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, fieldInfo); }; }
internal override AssignmentCallback EmitSet(CodeGenerator/*!*/ codeGenerator, IPlace instance, bool isRef, ConstructedType constructedType, bool runtimeVisibilityCheck) { Debug.Assert(IsStatic == (instance == null)); AdjustConstructedType(ref constructedType); if (IsStatic) { // check the visibility at runtime by the operator: if (runtimeVisibilityCheck || UpgradesVisibility) return codeGenerator.EmitSetStaticPropertyOperator(DeclaringType, this.FullName, null, isRef); if (isRef) { if (!IsAppStatic) Implementor.EmitThreadStaticInit(codeGenerator, constructedType); // just write the PhpReference to the field upon assignment return delegate(CodeGenerator codeGen, PhpTypeCode stackTypeCode) { codeGen.IL.Emit(OpCodes.Stsfld, DType.MakeConstructed(RealField, constructedType)); }; } else { // read the PhpReference stored in the field EmitGetInternal(codeGenerator, null, true, constructedType, false, false); // finish the assignment by writing to its Value field return delegate(CodeGenerator codeGen, PhpTypeCode stackTypeCode) { codeGen.IL.Emit(OpCodes.Stfld, Fields.PhpReference_Value); }; } } else { // direct access is possible, however, we have to be prepared for actually calling // the operator if the field proves to have been unset return delegate(CodeGenerator codeGen, PhpTypeCode stackTypeCode) { ILEmitter il = codeGen.IL; codeGen.EmitLoadSelf(); instance.EmitLoad(il); il.Emit(isRef ? OpCodes.Ldflda : OpCodes.Ldfld, DType.MakeConstructed(RealField, constructedType)); il.Emit(OpCodes.Ldstr, Name.ToString()); codeGen.EmitLoadClassContext(); if (isRef) { // CALL Operators.SetObjectFieldDirectRef(STACK,<target>,ref <field>,<field name>,<type desc>) il.Emit(OpCodes.Call, Methods.Operators.SetObjectFieldDirectRef); } else { // CALL Operators.SetObjectFieldDirect(STACK,<target>,<field>,<field name>,<type desc>) il.Emit(OpCodes.Call, Methods.Operators.SetObjectFieldDirect); } }; } }