private PhpTypeCode EmitNodeWrite(CodeGenerator codeGenerator) { ChainBuilder chain = codeGenerator.ChainBuilder; if (chain.IsMember) { // 1,4,5,6,9 if (this.isMemberOf != null) { // 1: ...->a->... chain.Lengthen(); chain.EmitEnsureProperty(isMemberOf, this, false); return(PhpTypeCode.DObject); } if (chain.IsArrayItem) { // 4,6 if (chain.IsLastMember) { // 4: a[][] chain.EmitEnsureVariableIsArray(this); } else { // 6: $b->a[3] ChainBuilder.ObjectFieldLazyEmitInfo object_info = chain.GetObjectForLazyEmit(); // Lengthen for hop over -> chain.EmitEnsureProperty(object_info.ObjectForLazyEmit, this, true); chain.ReleaseObjectForLazyEmit(object_info); chain.IsArrayItem = true; chain.IsLastMember = false; } return(PhpTypeCode.PhpArray); } if (chain.Exists) { // 5: $a->b->c->... chain.EmitEnsureVariableIsObject(this); return(PhpTypeCode.DObject); } else { // 9: $a->b this.EmitLoadAddress(codeGenerator); return(PhpTypeCode.ObjectAddress); } } // 2,3,7,8 if (this.isMemberOf != null) { // 2: $b->a // 8: b[]->a chain.Create(); chain.Begin(); assignmentCallback = EmitWriteField(codeGenerator, false); // Note: more work is done in EmitAssign // some data are preloaded but nothing that can be consumed is loaded on stack: return(PhpTypeCode.Unknown); } // 3,7 if (codeGenerator.ChainBuilder.IsArrayItem) { // 3: a[3] EmitLoadAddress(codeGenerator); return(PhpTypeCode.ObjectAddress); } else { // 7: $a EmitStorePrepare(codeGenerator); return(PhpTypeCode.Unknown); } }
private PhpTypeCode EmitNodeWrite(IndirectVarUse node, CodeGenerator codeGenerator) { ChainBuilder chain = codeGenerator.ChainBuilder; if (chain.IsMember) { // 1,4,5,6,9 if (node.IsMemberOf != null) { // 1: ...->$a->... chain.Lengthen(); chain.EmitEnsureProperty(node.IsMemberOf, node, false); return(PhpTypeCode.DObject); } if (chain.IsArrayItem) { // 4,6 if (chain.IsLastMember) { // 4: ${"a"}[][] chain.EmitEnsureVariableIsArray(node); return(PhpTypeCode.PhpArray); } else { // 6: $b->${"a"}[3] ChainBuilder.ObjectFieldLazyEmitInfo object_info = chain.GetObjectForLazyEmit(); // Lengthen for hop over -> chain.EmitEnsureProperty(object_info.ObjectForLazyEmit, node, true); chain.ReleaseObjectForLazyEmit(object_info); chain.IsArrayItem = true; chain.IsLastMember = false; return(PhpTypeCode.PhpArray); } } if (chain.Exists) { // 5: $$a->b->c->... chain.EmitEnsureVariableIsObject(node); return(PhpTypeCode.DObject); } else { // 9: $$a->b this.EmitLoadAddress(node, codeGenerator); return(PhpTypeCode.ObjectAddress); } } // 2,3,7,8 if (node.IsMemberOf != null) { // 2: $b->a // 8: b[]->a chain.Create(); chain.Begin(); assignmentCallback = EmitWriteField(node, codeGenerator, false); // Note: more work is done in EmitAssign return(PhpTypeCode.Unknown); } // 3,7 if (codeGenerator.ChainBuilder.IsArrayItem) { // 3: ${"a"}[3] this.EmitLoadAddress(node, codeGenerator); return(PhpTypeCode.ObjectAddress); } // 7: $a //codeGenerator.EmitVariableStorePrepare(this); this.EmitStorePrepare(node, codeGenerator); return(PhpTypeCode.Unknown); }