public void Dispose() { if (_loc != null) { _cg.ReturnTemporaryLocal(_loc); _loc = null; } else if (_tempName != null) { // <temporary>.RemoveKey(name) Debug.Assert(_cg.TemporalLocalsPlace != null); _cg.TemporalLocalsPlace.EmitLoad(_cg.Builder); _cg.EmitIntStringKey(_tempName); _cg.EmitPop(_cg.EmitCall(System.Reflection.Metadata.ILOpCode.Callvirt, _cg.CoreMethods.PhpArray.RemoveKey_IntStringKey)); _tempName = null; } }
void IBoundReference.EmitStorePrepare(CodeGenerator cg, InstanceCacheHolder instanceOpt) { // Template: array[index] EmitArrayPrepare(cg, instanceOpt); if (this.Index != null) { cg.EmitIntStringKey(this.Index); // TODO: save Index into InstanceCacheHolder } }
void IBoundReference.EmitLoadPrepare(CodeGenerator cg, InstanceCacheHolder instanceOpt) { // Template: array[index] EmitArrayPrepare(cg, instanceOpt); if (this.Index == null) throw new ArgumentException(); cg.EmitIntStringKey(this.Index); // TODO: save Index into InstanceCacheHolder }
internal override TypeSymbol Emit(CodeGenerator cg) { // new PhpArray(count) cg.Builder.EmitIntConstant(_items.Length); var result = cg.EmitCall(ILOpCode.Newobj, cg.CoreMethods.Ctors.PhpArray_int) .Expect(cg.CoreTypes.PhpArray); foreach (var x in _items) { // <PhpArray> cg.Builder.EmitOpCode(ILOpCode.Dup); // key if (x.Key != null) { cg.EmitIntStringKey(x.Key); } // value | alias Debug.Assert(x.Value != null); var byref = x.Value.Access.IsReadRef; var valuetype = byref ? cg.CoreTypes.PhpAlias : cg.CoreTypes.PhpValue; cg.EmitConvert(x.Value, valuetype); if (x.Key != null) { if (byref) // .SetItemAlias( key, PhpAlias ) cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpArray.SetItemAlias_IntStringKey_PhpAlias); else // .SetItemValue( key, PhpValue ) cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpArray.SetItemValue_IntStringKey_PhpValue); } else { if (byref) // PhpValue.Create( PhpAlias ) cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.Create_PhpAlias); // .AddValue( PhpValue ) cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpArray.AddValue_PhpValue); } } // return result; }
void IBoundReference.EmitStore(CodeGenerator cg, TypeSymbol valueType) { var rtype = cg.CoreTypes.IPhpArray; cg.EmitConvert(valueType, 0, rtype); var tmp = cg.GetTemporaryLocal(rtype); cg.Builder.EmitLocalStore(tmp); // NOTE: since PHP7, variables are assigned from left to right var vars = this.Variables; for (int i = 0; i < vars.Length; i++) { var target = vars[i]; if (target == null) continue; var boundtarget = target.BindPlace(cg); boundtarget.EmitStorePrepare(cg); // LOAD IPhpArray.GetItemValue(IntStringKey{i}) cg.Builder.EmitLocalLoad(tmp); cg.EmitIntStringKey(i); var itemtype = cg.EmitCall(ILOpCode.Callvirt, cg.CoreMethods.IPhpArray.GetItemValue_IntStringKey); // STORE vars[i] boundtarget.EmitStore(cg, itemtype); } // cg.ReturnTemporaryLocal(tmp); }
private void EmitPrepare(CodeGenerator cg, InstanceCacheHolder instanceOpt = null) { // Template: <variables> Key LoadVariablesArray(cg); // key cg.EmitIntStringKey(_nameExpr); }
internal override void EmitInit(CodeGenerator cg) { // TODO: check callable, iterable // TODO: ? if (cg.HasUnoptimizedLocals && $this) <locals>["this"] = ... var srcparam = _symbol as SourceParameterSymbol; if (srcparam != null) { var srcplace = new ParamPlace(_symbol); var routine = srcparam.Routine; if (cg.HasUnoptimizedLocals) { Debug.Assert(cg.LocalsPlaceOpt != null); // copy parameter to <locals>[Name] // <locals>[name] = value cg.LocalsPlaceOpt.EmitLoad(cg.Builder); // <locals> cg.EmitIntStringKey(new BoundLiteral(this.Name)); // [key] cg.EmitConvertToPhpValue(srcplace.EmitLoad(cg.Builder), 0); // value cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpArray.SetItemValue_IntStringKey_PhpValue); // _isUnoptimized = true; } else { // TODO: copy parameter by value in case of PhpValue, Array, PhpString // create local variable in case of parameter type is not enough for its use within routine if (_symbol.Type != cg.CoreTypes.PhpValue && _symbol.Type != cg.CoreTypes.PhpAlias) { var tmask = routine.ControlFlowGraph.GetLocalTypeMask(srcparam.Name); var clrtype = cg.DeclaringCompilation.GetTypeFromTypeRef(routine, tmask); if (clrtype != _symbol.Type) // Assert: only if clrtype is not covered by _symbol.Type { // TODO: performance warning _lazyLocal = new BoundLocal(new SynthesizedLocalSymbol(routine, srcparam.Name, clrtype)); _lazyLocal.EmitInit(cg); var localplace = _lazyLocal.Place(cg.Builder); // <local> = <param> localplace.EmitStorePrepare(cg.Builder); cg.EmitConvert(srcplace.EmitLoad(cg.Builder), 0, clrtype); localplace.EmitStore(cg.Builder); } } } } }