Emit_PhpValue_MakeAlias() public method

Emits new PhpAlias, expecting PhpValue on top of the evaluation stack.
public Emit_PhpValue_MakeAlias ( ) : TypeSymbol
return TypeSymbol
コード例 #1
0
ファイル: BoundExpression.cs プロジェクト: iolevel/peachpie
        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);
                }
            }
        }
コード例 #2
0
ファイル: Places.cs プロジェクト: iolevel/peachpie
        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);
            }
        }
コード例 #3
0
ファイル: Places.cs プロジェクト: iolevel/peachpie
        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);
                }
            }
        }
コード例 #4
0
ファイル: Places.cs プロジェクト: iolevel/peachpie
        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);
                }
            }
        }
コード例 #5
0
ファイル: Places.cs プロジェクト: iolevel/peachpie
        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;
                }
            }
        }