private void EmitPrepare(CodeGenerator cg, InstanceCacheHolder instanceOpt = null) { // Template: <variables> Key LoadVariablesArray(cg); // key cg.EmitIntStringKey(_nameExpr); }
public TypeSymbol TypeOpt => null; // PhpArray public void EmitLoadPrepare(CodeGenerator cg, InstanceCacheHolder instanceOpt = null) { // nothing }
public void EmitStorePrepare(CodeGenerator cg, InstanceCacheHolder instanceOpt = null) { // Context cg.EmitLoadContext(); }
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 }
/// <summary> /// Emits instance of the field containing class. /// </summary> protected virtual void EmitLoadFieldInstance(CodeGenerator cg, InstanceCacheHolder instanceOpt) { // instance var instancetype = InstanceCacheHolder.EmitInstance(instanceOpt, cg, Instance); // if (Field.IsStatic && Instance != null) cg.EmitPop(instancetype); else if (!Field.IsStatic && Instance == null) throw new NotImplementedException(); }
void IBoundReference.EmitStorePrepare(CodeGenerator cg, InstanceCacheHolder instanceOpt) { // nop }
internal override TypeSymbol Emit(CodeGenerator cg) { Debug.Assert(this.Access.IsNone || Access.IsRead); Debug.Assert(!this.Access.IsReadRef); Debug.Assert(!this.Access.IsWrite); Debug.Assert(this.Target.Access.IsRead && this.Target.Access.IsWrite); Debug.Assert(this.Value.Access.IsRead); Debug.Assert(this.Value is BoundLiteral); if (this.UsesOperatorMethod) { throw new NotImplementedException(); } TypeSymbol result_type = cg.CoreTypes.Void; LocalDefinition postfix_temp = null; var read = this.Access.IsRead; var target_place = this.Target.BindPlace(cg); Debug.Assert(target_place != null); using (var instance_holder = new InstanceCacheHolder()) { // prepare target for store operation target_place.EmitStorePrepare(cg, instance_holder); // load target value target_place.EmitLoadPrepare(cg, instance_holder); } var target_load_type = target_place.EmitLoad(cg); TypeSymbol op_type; if (read && IsPostfix) { // store original value of target // <temp> = TARGET postfix_temp = cg.GetTemporaryLocal(target_load_type); cg.EmitOpCode(ILOpCode.Dup); cg.Builder.EmitLocalStore(postfix_temp); } if (IsIncrement) { op_type = BoundBinaryEx.EmitAdd(cg, target_load_type, this.Value, target_place.TypeOpt); } else { Debug.Assert(IsDecrement); op_type = BoundBinaryEx.EmitSub(cg, target_load_type, this.Value, target_place.TypeOpt); } if (read) { if (IsPostfix) { // READ <temp> cg.Builder.EmitLocalLoad(postfix_temp); result_type = target_load_type; // cg.ReturnTemporaryLocal(postfix_temp); postfix_temp = null; } else { // dup resulting value // READ (++TARGET OR --TARGET) cg.Builder.EmitOpCode(ILOpCode.Dup); result_type = op_type; } } // target_place.EmitStore(cg, op_type); Debug.Assert(postfix_temp == null); Debug.Assert(!read || result_type.SpecialType != SpecialType.System_Void); // return result_type; }
public void EmitStorePrepare(CodeGenerator cg, InstanceCacheHolder instanceOpt = null) { if (_lazyStoreCallSite == null) _lazyStoreCallSite = cg.Factory.StartCallSite("set_" + this.NameValueOpt); // callsite.Target callsite _lazyStoreCallSite.EmitLoadTarget(cg.Builder); _lazyStoreCallSite.Place.EmitLoad(cg.Builder); _type.EmitLoadTypeInfo(cg); }
/// <summary> /// Emits instance. Caches the result if holder is provided, or loads evaluated instance if holder was initialized already. /// </summary> public static TypeSymbol EmitInstance(InstanceCacheHolder holderOrNull, CodeGenerator cg, BoundExpression instance) { return (instance != null) ? EmitInstance(holderOrNull, cg, () => cg.Emit(instance)) : null; }
public void EmitLoadPrepare(CodeGenerator cg, InstanceCacheHolder instanceOpt = null) { if (_lazyLoadCallSite == null) _lazyLoadCallSite = cg.Factory.StartCallSite("get_" + this.NameValueOpt); // callsite.Target callsite _lazyLoadCallSite.EmitLoadTarget(cg.Builder); _lazyLoadCallSite.Place.EmitLoad(cg.Builder); // instance InstanceCacheHolder.EmitInstance(instanceOpt, cg, Instance); }
public void EmitStorePrepare(CodeGenerator cg, InstanceCacheHolder instanceOpt = null) { if (_lazyStoreCallSite == null) _lazyStoreCallSite = cg.Factory.StartCallSite("set_" + this.NameValueOpt); // callsite.Target callsite _lazyStoreCallSite.EmitLoadTarget(cg.Builder); _lazyStoreCallSite.Place.EmitLoad(cg.Builder); // instance InstanceCacheHolder.EmitInstance(instanceOpt, cg, Instance); // NameExpression in case of indirect call if (!_name.IsDirect) { cg.EmitConvert(_name.NameExpression, cg.CoreTypes.String); } }
protected override void EmitLoadFieldInstance(CodeGenerator cg, InstanceCacheHolder instanceOpt) { // Template: <ctx>.GetStatics<_statics>().Field var statics = InstanceCacheHolder.EmitInstance(instanceOpt, cg, () => this.Field.ContainingType.EmitLoadStatics(cg)); if (statics == null) throw new InvalidOperationException(); }
public void EmitStorePrepare(CodeGenerator cg, InstanceCacheHolder instanceOpt) { Debug.Assert(Access.IsWrite); EmitLoadFieldInstance(cg, instanceOpt); // var type = Field.Type; if (Access.IsWriteRef) { // no need for preparation } else { // if (type == cg.CoreTypes.PhpAlias) { // (PhpAlias)<place> EmitOpCode_Load(cg); // PhpAlias } else if (type == cg.CoreTypes.PhpValue) { EmitOpCode_LoadAddress(cg); // &PhpValue } else { // no need for preparation } } }
public void EmitLoadPrepare(CodeGenerator cg, InstanceCacheHolder instanceOpt) { EmitLoadFieldInstance(cg, instanceOpt); }
public void EmitStorePrepare(CodeGenerator cg, InstanceCacheHolder instanceOpt = null) { EmitPrepare(cg, instanceOpt); }
public static TypeSymbol EmitInstance(InstanceCacheHolder holderOrNull, CodeGenerator cg, Func<TypeSymbol> emitter) { if (holderOrNull != null) { return holderOrNull.EmitInstance(cg, emitter); } else { return emitter(); } }
void IBoundReference.EmitLoadPrepare(CodeGenerator cg, InstanceCacheHolder instanceOpt) { throw new InvalidOperationException(); }
/// <summary> /// Emits name as string. Caches the result if holder is provided, or loads evaluated name if holder was initialized already. /// </summary> public static void EmitName(InstanceCacheHolder holderOrNull, CodeGenerator cg, BoundExpression name) { Contract.ThrowIfNull(cg); Contract.ThrowIfNull(name); if (holderOrNull != null) { holderOrNull.EmitName(cg, name); } else { cg.EmitConvert(name, cg.CoreTypes.String); } }
internal override TypeSymbol Emit(CodeGenerator cg) { Debug.Assert(Access.IsRead || Access.IsNone); // target X= value; var target_place = this.Target.BindPlace(cg); Debug.Assert(target_place != null); Debug.Assert(target_place.TypeOpt == null || target_place.TypeOpt.SpecialType != SpecialType.System_Void); // helper class maintaining reference to already evaluated instance of the eventual chain using (var instance_holder = new InstanceCacheHolder()) { // <target> = <target> X <value> target_place.EmitStorePrepare(cg, instance_holder); // target_place.EmitLoadPrepare(cg, instance_holder); } var xtype = target_place.EmitLoad(cg); // type of left value operand TypeSymbol result_type; switch (this.Operation) { case Operations.AssignAdd: result_type = BoundBinaryEx.EmitAdd(cg, xtype, Value, target_place.TypeOpt); break; //case Operations.AssignAnd: // binaryop = Operations.And; // break; case Operations.AssignAppend: result_type = EmitAppend(cg, xtype, Value); break; ////case Operations.AssignPrepend: //// break; case Operations.AssignDiv: result_type = BoundBinaryEx.EmitDiv(cg, xtype, Value, target_place.TypeOpt); break; //case Operations.AssignMod: // binaryop = Operations.Mod; // break; case Operations.AssignMul: result_type = BoundBinaryEx.EmitMul(cg, xtype, Value, target_place.TypeOpt); break; //case Operations.AssignOr: // binaryop = Operations.Or; // break; case Operations.AssignPow: result_type = BoundBinaryEx.EmitPow(cg, xtype, /*this.Target.TypeRefMask*/0, Value); break; //case Operations.AssignShiftLeft: // binaryop = Operations.ShiftLeft; // break; //case Operations.AssignShiftRight: // binaryop = Operations.ShiftRight; // break; case Operations.AssignSub: result_type = BoundBinaryEx.EmitSub(cg, xtype, Value, target_place.TypeOpt); break; //case Operations.AssignXor: // binaryop = Operations.Xor; // break; default: throw ExceptionUtilities.UnexpectedValue(this.Operation); } LocalDefinition tmp = null; switch (this.Access.Flags) { case AccessMask.Read: tmp = cg.GetTemporaryLocal(result_type, false); cg.Builder.EmitOpCode(ILOpCode.Dup); cg.Builder.EmitLocalStore(tmp); break; case AccessMask.None: break; default: throw ExceptionUtilities.UnexpectedValue(this.Access); } target_place.EmitStore(cg, result_type); // switch (this.Access.Flags) { case AccessMask.None: return cg.CoreTypes.Void; case AccessMask.Read: Debug.Assert(tmp != null); cg.Builder.EmitLoad(tmp); cg.ReturnTemporaryLocal(tmp); return result_type; default: throw ExceptionUtilities.UnexpectedValue(this.Access); } }
public void EmitLoadPrepare(CodeGenerator cg, InstanceCacheHolder instanceOpt) { }
void EmitArrayPrepare(CodeGenerator cg, InstanceCacheHolder instanceOpt) { InstanceCacheHolder.EmitInstance(instanceOpt, cg, Array); if (Array.ResultType.IsOfType(cg.CoreTypes.IPhpArray)) { // ok } else if (Array.ResultType == cg.CoreTypes.PhpValue) { // Convert.ToArray() cg.EmitCall(ILOpCode.Call, cg.CoreMethods.Operators.ToArray_PhpValue); } else if (Array.ResultType == cg.CoreTypes.String) { // new PhpString(string) cg.EmitCall(ILOpCode.Newobj, cg.CoreMethods.Ctors.PhpString_string); } else if (Array.ResultType == cg.CoreTypes.Void) { // TODO: uninitialized value, report error Debug.WriteLine("Use of uninitialized value."); cg.EmitCall(ILOpCode.Newobj, cg.CoreMethods.Ctors.PhpString); } else { throw new NotImplementedException(); // TODO: emit convert as PhpArray } }
public void EmitStorePrepare(CodeGenerator cg, InstanceCacheHolder instanceOpt) { var type = _place.TypeOpt; if (_access.IsWriteRef) { // no need for preparation _place.EmitStorePrepare(cg.Builder); } else { // if (type == cg.CoreTypes.PhpAlias) { // (PhpAlias)<place> _place.EmitLoad(cg.Builder); } else if (type == cg.CoreTypes.PhpValue) { if (_thint.IsRef) { // Operators.SetValue(ref <place>, (PhpValue)<value>); _place.EmitLoadAddress(cg.Builder); } else { _place.EmitStorePrepare(cg.Builder); } } else { // no need for preparation _place.EmitStorePrepare(cg.Builder); } } }
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 } }
public void EmitStorePrepare(CodeGenerator cg, InstanceCacheHolder instanceOpt) { if (_property == null) { // TODO: callsite.Target callsite throw new NotImplementedException(); } InstanceCacheHolder.EmitInstance(instanceOpt, cg, _instance); }