internal ForeachMoveNextEdge(BoundBlock/*!*/source, BoundBlock/*!*/body, BoundBlock/*!*/end, ForeachEnumereeEdge/*!*/enumereeEdge, BoundReferenceExpression keyVar, BoundReferenceExpression/*!*/valueVar) : base(source) { Contract.ThrowIfNull(body); Contract.ThrowIfNull(end); Contract.ThrowIfNull(enumereeEdge); _body = body; _end = end; _enumereeEdge = enumereeEdge; _keyVariable = keyVar; _valueVariable = valueVar; Connect(source); }
internal void EmitGetCurrent(CodeGenerator cg, BoundReferenceExpression valueVar, BoundReferenceExpression keyVar) { Debug.Assert(_enumeratorLoc != null); var enumeratorPlace = new LocalPlace(_enumeratorLoc); if (valueVar is BoundListEx) { throw new NotImplementedException(); // TODO: list(vars) = enumerator.GetCurrent() } if (_currentValue != null && _currentKey != null) { // special PhpArray enumerator if (keyVar != null) { //cg.EmitSequencePoint(keyVar.PhpSyntax); var keyTarget = keyVar.BindPlace(cg); keyTarget.EmitStorePrepare(cg); keyTarget.EmitStore(cg, cg.EmitGetProperty(enumeratorPlace, _currentKey)); } //cg.EmitSequencePoint(valueVar.PhpSyntax); var valueTarget = valueVar.BindPlace(cg); valueTarget.EmitStorePrepare(cg); valueTarget.EmitStore(cg, cg.EmitGetProperty(enumeratorPlace, _currentValue)); } else { Debug.Assert(_current != null); if (keyVar != null) { throw new InvalidOperationException(); } var valueTarget = valueVar.BindPlace(cg); valueTarget.EmitStorePrepare(cg); var t = cg.EmitGetProperty(enumeratorPlace, _current); // TOOD: PhpValue.FromClr valueTarget.EmitStore(cg, t); } }
internal void EmitGetCurrent(CodeGenerator cg, BoundReferenceExpression valueVar, BoundReferenceExpression keyVar) { Debug.Assert(_enumeratorLoc != null); var enumeratorPlace = new LocalPlace(_enumeratorLoc); if (valueVar is BoundListEx) { throw new NotImplementedException(); // TODO: list(vars) = enumerator.GetCurrent() } if (_currentValue != null && _currentKey != null) { // special PhpArray enumerator cg.EmitSequencePoint(valueVar.PhpSyntax); var valueTarget = valueVar.BindPlace(cg); valueTarget.EmitStorePrepare(cg); valueTarget.EmitStore(cg, cg.EmitGetProperty(enumeratorPlace, _currentValue)); if (keyVar != null) { cg.EmitSequencePoint(keyVar.PhpSyntax); var keyTarget = keyVar.BindPlace(cg); keyTarget.EmitStorePrepare(cg); keyTarget.EmitStore(cg, cg.EmitGetProperty(enumeratorPlace, _currentKey)); } } else { Debug.Assert(_current != null); if (keyVar != null) { throw new InvalidOperationException(); } cg.EmitSequencePoint(valueVar.PhpSyntax); var valueTarget = valueVar.BindPlace(cg); valueTarget.EmitStorePrepare(cg); var t = cg.EmitGetProperty(enumeratorPlace, _current); // TOOD: PhpValue.FromClr valueTarget.EmitStore(cg, t); } }
internal void EmitGetCurrent(CodeGenerator cg, BoundReferenceExpression valueVar, BoundReferenceExpression keyVar) { Debug.Assert(_enumeratorLoc.IsValid); // NOTE: PHP writes first to {valueVar} then to {keyVar} if (_currentValue != null && _currentKey != null) { // special PhpArray enumerator cg.EmitSequencePoint(valueVar.PhpSyntax); var valueTarget = valueVar.BindPlace(cg); valueTarget.EmitStorePrepare(cg); valueTarget.EmitStore(cg, cg.EmitGetProperty(_enumeratorLoc, _currentValue)); if (keyVar != null) { cg.EmitSequencePoint(keyVar.PhpSyntax); var keyTarget = keyVar.BindPlace(cg); keyTarget.EmitStorePrepare(cg); keyTarget.EmitStore(cg, cg.EmitGetProperty(_enumeratorLoc, _currentKey)); } } else { Debug.Assert(_current != null); Debug.Assert(_current.GetMethod != null); var valuetype = _current.GetMethod.ReturnType; // ValueTuple (key, value) // TODO: KeyValuePair<key, value> // the same if (valuetype.Name == "ValueTuple" && valuetype.IsValueType && ((NamedTypeSymbol)valuetype).Arity == 2) { // tmp = current; var tmp = cg.GetTemporaryLocal(valuetype); cg.EmitGetProperty(_enumeratorLoc, _current); cg.Builder.EmitLocalStore(tmp); // TODO: ValueTuple Helper var item1 = valuetype.GetMembers("Item1").Single() as FieldSymbol; var item2 = valuetype.GetMembers("Item2").Single() as FieldSymbol; var item1place = new FieldPlace(new LocalPlace(tmp), item1, cg.Module); var item2place = new FieldPlace(new LocalPlace(tmp), item2, cg.Module); // value = tmp.Item2; cg.EmitSequencePoint(valueVar.PhpSyntax); var valueTarget = valueVar.BindPlace(cg); valueTarget.EmitStorePrepare(cg); valueTarget.EmitStore(cg, item2place.EmitLoad(cg.Builder)); // key = tmp.Item1; if (keyVar != null) { cg.EmitSequencePoint(keyVar.PhpSyntax); var keyTarget = keyVar.BindPlace(cg); keyTarget.EmitStorePrepare(cg); keyTarget.EmitStore(cg, item1place.EmitLoad(cg.Builder)); } // cg.ReturnTemporaryLocal(tmp); } // just a value else { cg.EmitSequencePoint(valueVar.PhpSyntax); var valueTarget = valueVar.BindPlace(cg); valueTarget.EmitStorePrepare(cg); var t = cg.EmitGetProperty(_enumeratorLoc, _current); // TOOD: PhpValue.FromClr valueTarget.EmitStore(cg, t); if (keyVar != null) { throw new InvalidOperationException(); } } } }
internal void EmitGetCurrent(CodeGenerator cg, BoundReferenceExpression valueVar, BoundReferenceExpression keyVar) { Debug.Assert(_enumeratorLoc.IsValid); // NOTE: PHP writes first to {valueVar} then to {keyVar} if (_currentValue != null && _currentKey != null) { // PhpArray enumerator or Iterator cg.EmitSequencePoint(valueVar.PhpSyntax); valueVar.BindPlace(cg).EmitStore(cg, () => EmitGetCurrentHelper(cg), valueVar.TargetAccess()); if (keyVar != null) { cg.EmitSequencePoint(keyVar.PhpSyntax); keyVar.BindPlace(cg).EmitStore(cg, () => VariableReferenceExtensions.EmitLoadValue(cg, _currentKey, _enumeratorLoc), keyVar.TargetAccess()); } } else { if (_current == null) { throw Roslyn.Utilities.ExceptionUtilities.UnexpectedValue(_current); } var valuetype = _current.ReturnType; // ValueTuple<T1, T2> (Item1, Item2) // KeyValuePair<TKey, TValue> (Key, Value) if (IsAPairValue(valuetype, out var skey, out var svalue)) { // tmp = current; var tmp = cg.GetTemporaryLocal(valuetype); VariableReferenceExtensions.EmitLoadValue(cg, _current, _enumeratorLoc); cg.Builder.EmitLocalStore(tmp); var tmploc = new LocalPlace(tmp); var keyplace = skey switch { FieldSymbol fld => (IPlace) new FieldPlace(tmploc, fld, cg.Module), PropertySymbol prop => new PropertyPlace(tmploc, prop, cg.Module), _ => throw Roslyn.Utilities.ExceptionUtilities.Unreachable, }; var valueplace = svalue switch { FieldSymbol fld => (IPlace) new FieldPlace(tmploc, fld, cg.Module), PropertySymbol prop => new PropertyPlace(tmploc, prop, cg.Module), _ => throw Roslyn.Utilities.ExceptionUtilities.Unreachable, }; // value = tmp.Item2; cg.EmitSequencePoint(valueVar.PhpSyntax); valueVar.BindPlace(cg).EmitStore(cg, valueplace, valueVar.TargetAccess()); // key = tmp.Item1; if (keyVar != null) { cg.EmitSequencePoint(keyVar.PhpSyntax); keyVar.BindPlace(cg).EmitStore(cg, keyplace, keyVar.TargetAccess()); } // cg.ReturnTemporaryLocal(tmp); }