public Emit_PhpValue_MakeAlias ( ) : TypeSymbol | ||
return | TypeSymbol |
void IBoundReference.EmitStore(CodeGenerator cg, TypeSymbol valueType) { // Template: array[index] var isphparr = (this.Array.ResultType == cg.CoreTypes.PhpArray); // whether the target is instance of PhpArray, otherwise it is an IPhpArray and we have to use .callvirt if (Access.IsWriteRef) { // PhpAlias if (valueType != cg.CoreTypes.PhpAlias) { cg.EmitConvertToPhpValue(valueType, 0); cg.Emit_PhpValue_MakeAlias(); } // .SetItemAlias(key, alias) or .AddValue(PhpValue.Create(alias)) if (this.Index != null) { if (isphparr) cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpArray.SetItemAlias_IntStringKey_PhpAlias); else cg.EmitCall(ILOpCode.Callvirt, cg.CoreMethods.IPhpArray.SetItemAlias_IntStringKey_PhpAlias); } else { cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.Create_PhpAlias); if (isphparr) cg.EmitCall(ILOpCode.Callvirt, cg.CoreMethods.IPhpArray.AddValue_PhpValue); else cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpArray.AddValue_PhpValue); } } else if (Access.IsUnset) { if (this.Index == null) throw new InvalidOperationException(); // .RemoveKey(key) if (isphparr) cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpArray.RemoveKey_IntStringKey); else cg.EmitCall(ILOpCode.Callvirt, cg.CoreMethods.IPhpArray.RemoveKey_IntStringKey); } else { Debug.Assert(Access.IsWrite); cg.EmitConvertToPhpValue(valueType, 0); // .SetItemValue(key, value) or .AddValue(value) if (this.Index != null) { if (isphparr) cg.EmitCall(ILOpCode.Callvirt, cg.CoreMethods.IPhpArray.SetItemValue_IntStringKey_PhpValue); else cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpArray.SetItemValue_IntStringKey_PhpValue); } else { if (isphparr) cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpArray.AddValue_PhpValue); else cg.EmitCall(ILOpCode.Callvirt, cg.CoreMethods.IPhpArray.AddValue_PhpValue); } } }
public virtual void EmitStore(CodeGenerator cg, TypeSymbol valueType) { // STACK: <PhpArray> <key> if (_access.IsWriteRef) { // PhpAlias if (valueType != cg.CoreTypes.PhpAlias) { cg.EmitConvertToPhpValue(valueType, 0); cg.Emit_PhpValue_MakeAlias(); } // .SetItemAlias(key, alias) cg.EmitCall(ILOpCode.Callvirt, cg.CoreMethods.PhpArray.SetItemAlias_IntStringKey_PhpAlias); } else if (_access.IsUnset) { Debug.Assert(valueType == null); // .RemoveKey(key) cg.EmitCall(ILOpCode.Callvirt, cg.CoreMethods.PhpArray.RemoveKey_IntStringKey); } else { Debug.Assert(_access.IsWrite); cg.EmitConvertToPhpValue(valueType, 0); // .SetItemValue(key, value) cg.EmitCall(ILOpCode.Callvirt, cg.CoreMethods.PhpArray.SetItemValue_IntStringKey_PhpValue); } }
public TypeSymbol EmitLoad(CodeGenerator cg) { Debug.Assert(_access.IsRead); var type = _place.TypeOpt; // Ensure Object ($x->.. =) if (_access.EnsureObject) { if (type == cg.CoreTypes.PhpAlias) { _place.EmitLoad(cg.Builder); return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpAlias.EnsureObject) .Expect(SpecialType.System_Object); } else if (type == cg.CoreTypes.PhpValue) { _place.EmitLoadAddress(cg.Builder); cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.EnsureObject) .Expect(SpecialType.System_Object); if (_thint.IsSingleType && cg.IsClassOnly(_thint)) { var tref = cg.Routine.TypeRefContext.GetTypes(_thint)[0]; var clrtype = (TypeSymbol)cg.DeclaringCompilation.GetTypeByMetadataName(tref.QualifiedName.ClrName()); if (clrtype != null && !clrtype.IsErrorType() && clrtype != cg.CoreTypes.Object) { cg.EmitCastClass(clrtype); return clrtype; } } return cg.CoreTypes.Object; } else if (type.IsOfType(cg.CoreTypes.IPhpArray)) { // PhpArray -> stdClass // PhpString -> stdClass (?) // otherwise keep the instance on stack throw new NotImplementedException(); } else { if (type.IsReferenceType) { if (type == cg.CoreTypes.Object) { // Operators.EnsureObject(ref <place>) _place.EmitLoadAddress(cg.Builder); return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.Operators.EnsureObject_ObjectRef) .Expect(SpecialType.System_Object); } else { // <place> return _place.EmitLoad(cg.Builder); } } else { // return new stdClass(ctx) throw new NotImplementedException(); } } } // Ensure Array ($x[] =) else if (_access.EnsureArray) { if (type == cg.CoreTypes.PhpAlias) { // <place>.EnsureArray() _place.EmitLoad(cg.Builder); return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpAlias.EnsureArray) .Expect(cg.CoreTypes.IPhpArray); } else if (type == cg.CoreTypes.PhpValue) { if (cg.IsArrayOnly(_thint)) { // uses typehint and accesses .Array directly if possible // <place>.Array _place.EmitLoadAddress(cg.Builder); return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.get_Array) .Expect(cg.CoreTypes.PhpArray); } else { // <place>.EnsureArray() _place.EmitLoadAddress(cg.Builder); return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.EnsureArray) .Expect(cg.CoreTypes.IPhpArray); } } else if (type.IsOfType(cg.CoreTypes.IPhpArray)) { // Operators.EnsureArray(ref <place>) _place.EmitLoadAddress(cg.Builder); if (type == cg.CoreTypes.PhpArray) { return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.Operators.EnsureArray_PhpArrayRef) .Expect(cg.CoreTypes.PhpArray); } else { return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.Operators.EnsureArray_IPhpArrayRef) .Expect(cg.CoreTypes.IPhpArray); } } throw new NotImplementedException("EnsureArray(" + type.Name + ")"); } // Ensure Alias (&$x) else if (_access.IsReadRef) { if (type == cg.CoreTypes.PhpAlias) { // TODO: <place>.AddRef() return _place.EmitLoad(cg.Builder); } else if (type == cg.CoreTypes.PhpValue) { // return <place>.EnsureAlias() _place.EmitLoadAddress(cg.Builder); return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.EnsureAlias) .Expect(cg.CoreTypes.PhpAlias); } else if (type == cg.CoreTypes.PhpNumber) { throw new NotImplementedException(); } else { Debug.Assert(false, "value cannot be aliased"); // new PhpAlias((PhpValue)<place>, 1) cg.EmitConvertToPhpValue(_place.EmitLoad(cg.Builder), 0); return cg.Emit_PhpValue_MakeAlias(); } } // Read Value & Dereference eventually else { if (type == cg.CoreTypes.PhpAlias) { _place.EmitLoad(cg.Builder); if (_access.TargetType == cg.CoreTypes.PhpArray) { // <place>.Value.ToArray() cg.Builder.EmitOpCode(ILOpCode.Ldflda); cg.EmitSymbolToken(cg.CoreMethods.PhpAlias.Value, null); return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.ToArray) .Expect(cg.CoreTypes.PhpArray); } return cg.Emit_PhpAlias_GetValue(); } else if (type == cg.CoreTypes.PhpValue) { if (_access.TargetType == cg.CoreTypes.PhpArray) { // <place>.ToArray() _place.EmitLoadAddress(cg.Builder); return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.ToArray) .Expect(cg.CoreTypes.PhpArray); } // TODO: dereference if applicable (=> PhpValue.Alias.Value) return _place.EmitLoad(cg.Builder); } else { return _place.EmitLoad(cg.Builder); } } }
public void EmitStore(CodeGenerator cg, TypeSymbol valueType) { var type = _place.TypeOpt; // Write Ref if (_access.IsWriteRef) { if (valueType != cg.CoreTypes.PhpAlias) { Debug.Assert(false, "caller should get aliased value"); cg.EmitConvertToPhpValue(valueType, 0); valueType = cg.Emit_PhpValue_MakeAlias(); } // if (type == cg.CoreTypes.PhpAlias) { // <place> = <alias> _place.EmitStore(cg.Builder); } else if (type == cg.CoreTypes.PhpValue) { // <place> = PhpValue.Create(<alias>) cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.Create_PhpAlias); _place.EmitStore(cg.Builder); } else { Debug.Assert(false, "Assigning alias to non-aliasable variable."); cg.EmitConvert(valueType, 0, type); _place.EmitStore(cg.Builder); } } else if (_access.IsUnset) { Debug.Assert(valueType == null); // <place> = if (type == cg.CoreTypes.PhpAlias) { // new PhpAlias(void) cg.Emit_PhpValue_Void(); cg.Emit_PhpValue_MakeAlias(); } else if (type.IsReferenceType) { // null cg.Builder.EmitNullConstant(); } else { // default(T) cg.EmitLoadDefaultOfValueType(type); } _place.EmitStore(cg.Builder); } else { // if (type == cg.CoreTypes.PhpAlias) { // <place>.Value = <value> cg.EmitConvertToPhpValue(valueType, 0); cg.Emit_PhpAlias_SetValue(); } else if (type == cg.CoreTypes.PhpValue) { if (_thint.IsRef) { // Operators.SetValue(ref <place>, (PhpValue)<value>); cg.EmitConvertToPhpValue(valueType, 0); cg.EmitCall(ILOpCode.Call, cg.CoreMethods.Operators.SetValue_PhpValueRef_PhpValue); } else { // <place> = <value> cg.EmitConvertToPhpValue(valueType, 0); _place.EmitStore(cg.Builder); } } else { cg.EmitConvert(valueType, 0, type); _place.EmitStore(cg.Builder); } } }
public TypeSymbol EmitLoad(CodeGenerator cg) { Debug.Assert(Access.IsRead); var type = Field.Type; // Ensure Object (..->Field->.. =) if (Access.EnsureObject) { if (type == cg.CoreTypes.PhpAlias) { EmitOpCode_Load(cg); // PhpAlias return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpAlias.EnsureObject) .Expect(SpecialType.System_Object); } else if (type == cg.CoreTypes.PhpValue) { EmitOpCode_LoadAddress(cg); // &PhpValue return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.EnsureObject) .Expect(SpecialType.System_Object); } else { if (type.IsReferenceType) { // TODO: ensure it is not null EmitOpCode_Load(cg); return type; } else { // return new stdClass(ctx) throw new NotImplementedException(); } } } // Ensure Array (xxx->Field[] =) else if (Access.EnsureArray) { if (type == cg.CoreTypes.PhpAlias) { EmitOpCode_Load(cg); return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpAlias.EnsureArray) .Expect(cg.CoreTypes.IPhpArray); } else if (type == cg.CoreTypes.PhpValue) { EmitOpCode_LoadAddress(cg); return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.EnsureArray) .Expect(cg.CoreTypes.IPhpArray); } else if (type.IsOfType(cg.CoreTypes.IPhpArray)) { EmitOpCode_LoadAddress(cg); // ensure value is not null if (type == cg.CoreTypes.PhpArray) { return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.Operators.EnsureArray_PhpArrayRef) .Expect(cg.CoreTypes.PhpArray); } else { return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.Operators.EnsureArray_IPhpArrayRef) .Expect(cg.CoreTypes.IPhpArray); } } throw new NotImplementedException(); } // Ensure Alias (&...->Field) else if (Access.IsReadRef) { if (type == cg.CoreTypes.PhpAlias) { // TODO: <place>.AddRef() EmitOpCode_Load(cg); return type; } else if (type == cg.CoreTypes.PhpValue) { // return <place>.EnsureAlias() EmitOpCode_LoadAddress(cg); // &PhpValue return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.EnsureAlias) .Expect(cg.CoreTypes.PhpAlias); } else { Debug.Assert(false, "value cannot be aliased"); // new PhpAlias((PhpValue)<place>, 1) EmitOpCode_Load(cg); cg.EmitConvertToPhpValue(type, 0); return cg.Emit_PhpValue_MakeAlias(); } } // Read (...->Field) & Dereference eventually else { if (type == cg.CoreTypes.PhpAlias) { EmitOpCode_Load(cg); if (Access.TargetType != null) { // convert PhpValue to target type without loading whole value and storing to temporary variable switch (Access.TargetType.SpecialType) { default: if (Access.TargetType == cg.CoreTypes.PhpArray) { // <PhpAlias>.Value.ToArray() cg.Builder.EmitOpCode(ILOpCode.Ldflda); cg.EmitSymbolToken(cg.CoreMethods.PhpAlias.Value, null); return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.ToArray); } break; } } return cg.Emit_PhpAlias_GetValue(); } else if (type == cg.CoreTypes.PhpValue) { if (Access.TargetType != null) { // convert PhpValue to target type without loading whole value and storing to temporary variable switch (Access.TargetType.SpecialType) { case SpecialType.System_Double: EmitOpCode_LoadAddress(cg); // &PhpValue.ToDouble() return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.ToDouble); case SpecialType.System_Int64: EmitOpCode_LoadAddress(cg); // &PhpValue.ToLong() return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.ToLong); case SpecialType.System_Boolean: EmitOpCode_LoadAddress(cg); // &PhpValue.ToBoolean() return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.ToBoolean); case SpecialType.System_String: EmitOpCode_LoadAddress(cg); // &PhpValue.ToString(ctx) cg.EmitLoadContext(); return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.ToString_Context); case SpecialType.System_Object: EmitOpCode_LoadAddress(cg); // &PhpValue.ToClass() return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.ToClass); default: if (Access.TargetType == cg.CoreTypes.PhpArray) { EmitOpCode_LoadAddress(cg); // &PhpValue.ToArray() return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.ToArray); } break; } } // TODO: dereference if applicable (=> PhpValue.Alias.Value) EmitOpCode_Load(cg); return type; } else { EmitOpCode_Load(cg); return type; } } }