本文整理汇总了C#中PHP.Core.AST.Expression.Emit方法的典型用法代码示例。如果您正苦于以下问题:C# Expression.Emit方法的具体用法?C# Expression.Emit怎么用?C# Expression.Emit使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类PHP.Core.AST.Expression
的用法示例。
在下文中一共展示了Expression.Emit方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: EmitArrayKey
internal PhpTypeCode EmitArrayKey(ChainBuilder chain, Expression key)
{
PhpTypeCode result;
if (key != null)
{
if (chain != null) chain.Create();
// convert the key into integer if necessary and possible in compile time
IntStringKey array_key;
if (key.HasValue() && Convert.ObjectToArrayKey(key.GetValue(), out array_key) && array_key.IsInteger)
{
il.LdcI4(array_key.Integer);
result = PhpTypeCode.Integer;
}
else
{
// Emit index and box the result
switch (result = key.Emit(this))
{
case PhpTypeCode.Integer:
break;
case PhpTypeCode.String:
break;
default:
EmitBoxing(result);
result = PhpTypeCode.Object;
break;
}
}
if (chain != null) chain.End();
}
else
result = PhpTypeCode.Invalid;
return result;
}
示例2: EmitObjectToBoolean
/// <summary>
/// Emits conversion to boolean.
/// </summary>
/// <param name="expr">Expression to be converted.</param>
/// <param name="negation">Whether the result should be logic negation of original conversion.</param>
internal void EmitObjectToBoolean(Expression/*!*/expr, bool negation)
{
// <expr>
var typecode = expr.Emit(this);
//
switch (typecode)
{
case PhpTypeCode.Boolean:
if (negation)
this.EmitLogicNegation();
break;
case PhpTypeCode.Integer:
// <int> != 0
this.EmitLogicNegation();
if (!negation)
this.EmitLogicNegation();
break;
case PhpTypeCode.LongInteger:
// <long> != 0
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Conv_I8);
il.Emit(OpCodes.Ceq);
if (!negation)
this.EmitLogicNegation();
break;
case PhpTypeCode.Double:
// <double> != 0.0
il.Emit(OpCodes.Ldc_R8, 0.0);
il.Emit(OpCodes.Ceq);
if (!negation)
this.EmitLogicNegation();
break;
case PhpTypeCode.Void:
if (negation)
il.Emit(OpCodes.Ldc_I4_1);
else
il.Emit(OpCodes.Ldc_I4_0);
break;
case PhpTypeCode.String:
// StringToBoolean( <string> )
IL.Emit(OpCodes.Call, Methods.Convert.StringToBoolean);
if (negation)
this.EmitLogicNegation();
break;
default:
// ObjectToBoolean( (object)<expr> )
EmitBoxing(typecode);
IL.Emit(OpCodes.Call, Methods.Convert.ObjectToBoolean);
if (negation)
this.EmitLogicNegation();
break;
}
}
示例3: EmitConversion
/// <summary>
/// Emits IL instructions that convert the top of evaluation stack to a specified type.
/// </summary>
/// <remarks>
/// Emits a call to one of <see cref="PHP.Core.Convert"/> methods to do the conversion.
/// The method result is left on the evaluation stack.
/// </remarks>
internal void EmitConversion(Expression/*!*/ expression, PhpTypeCode dst)
{
// expression is evaluable:
if (expression.HasValue())
{
switch (dst)
{
case PhpTypeCode.String:
il.Emit(OpCodes.Ldstr, PHP.Core.Convert.ObjectToString(expression.GetValue()));
break;
case PhpTypeCode.Boolean:
il.LdcI4(PHP.Core.Convert.ObjectToBoolean(expression.GetValue()) ? 1 : 0);
break;
case PhpTypeCode.Integer:
il.LdcI4(PHP.Core.Convert.ObjectToInteger(expression.GetValue()));
break;
case PhpTypeCode.Double:
il.Emit(OpCodes.Ldc_R8, PHP.Core.Convert.ObjectToDouble(expression.GetValue()));
break;
case PhpTypeCode.Object:
il.LoadLiteral(expression.GetValue());
break;
default:
Debug.Fail("Conversion not implemented.");
break;
}
}
else
{
// emits the expression:
PhpTypeCode src = expression.Emit(this);
// emits no conversion if types are the same:
if (src == dst) return;
// emits boxing if needed (conversion methods takes object):
EmitBoxing(src);
switch (dst)
{
case PhpTypeCode.String:
il.Emit(OpCodes.Call, Methods.Convert.ObjectToString);
break;
case PhpTypeCode.Boolean:
il.Emit(OpCodes.Call, Methods.Convert.ObjectToBoolean);
break;
case PhpTypeCode.Integer:
il.Emit(OpCodes.Call, Methods.Convert.ObjectToBoolean);
break;
case PhpTypeCode.Double:
il.Emit(OpCodes.Call, Methods.Convert.ObjectToDouble);
break;
case PhpTypeCode.Object:
// nop //
break;
default:
Debug.Fail("Conversion is not implemented.");
break;
}
}
}
示例4: EmitEval
/// <summary>
/// Emit call to <see cref="DynamicCode.Assert"/> or <see cref="DynamicCode.Eval"/>.
/// </summary>
internal PhpTypeCode EmitEval(EvalKinds kind, Expression/*!*/code, Text.Span span, QualifiedName? currentNamespace, Dictionary<string, QualifiedName> currentAliases)
{
Debug.Assert(code != null);
// LOAD DynamicCode.<Eval | Assert>(<code>, context, definedVariables, self, includer, source, line, column, evalId, naming)
if (kind == EvalKinds.Assert)
{
// an argument of the assert is boxed:
EmitBoxing(code.Emit(this));
}
else if (kind == EvalKinds.SyntheticEval)
{
Debug.Assert(code.HasValue());
Debug.Assert(code.GetValue() is string);
// an argument of the eval is converted to a string:
il.Emit(OpCodes.Ldstr, (string)code.GetValue());
il.Emit(OpCodes.Ldc_I4_1);
}
else
{
// an argument of the eval is converted to a string:
EmitConversion(code, PhpTypeCode.String);
il.Emit(OpCodes.Ldc_I4_0);
}
var position = new Text.TextPoint(this.SourceUnit.LineBreaks, span.Start);
EmitLoadScriptContext();
EmitLoadRTVariablesTable();
EmitLoadSelf();
EmitLoadClassContext();
EmitEvalInfoPass(position.Line, position.Column);
EmitNamingContext(currentNamespace, currentAliases, span.Start);
il.Emit(OpCodes.Call, (kind == EvalKinds.Assert) ? Methods.DynamicCode.Assert : Methods.DynamicCode.Eval);
return (kind == EvalKinds.Assert) ? PhpTypeCode.Boolean : PhpTypeCode.Object;
}
示例5: EmitEcho
/// <summary>
/// Emits IL instructions to process the <B>echo</B> and <B>print</B> commands.
/// </summary>
/// <param name="parameter">Expression to be sent to output.</param>
public void EmitEcho(Expression parameter)
{
// Template:
// context.Echo(value);
ConcatEx concat;
//BinaryEx binary_expr;
if ((concat = parameter as ConcatEx) != null && concat.Expressions.Length > 1)
{
//foreach (Expression expr in concat.Expressions)
//{
// EmitLoadScriptContext();
// EmitEchoCall(expr.Emit(this));
//}
// obsolete: (but expressions must be first emitted and processed, then echoed)
// array = new object[] { expr1, expr2, ..., exprn };
//LocalBuilder array = EmitObjectArrayPopulation(concat.Expressions, null);
//// context.Echo(array);
//EmitLoadScriptContext();
//il.Ldloc(array);
//il.Emit(OpCodes.Call, Methods.ScriptContext.Echo.ObjectArray);
EmitEcho(concat.Expressions);
}
//// obsolete: wrong order of expressions execution (evaluate first, then echo!)
//else if ((binary_expr = parameter as BinaryEx) != null && binary_expr.Operation == Operations.Concat)
//{
// // context.Echo(<left>)
// EmitLoadScriptContext();
// EmitEchoCall(binary_expr.LeftExpr.Emit(this));
// // context.Echo(<right>)
// EmitLoadScriptContext();
// EmitEchoCall(binary_expr.RightExpr.Emit(this));
//}
else
{
var typecode = parameter.Emit(this);
EmitLoadScriptContext();
// CALL ScriptContext.Echo(<parameter>, <context>)
EmitEchoStaticCall(typecode);
}
}
示例6: EmitRoutineOperatorCall
/// <summary>
/// Emits a call to a routine with specified name using an operator.
/// </summary>
internal PhpTypeCode EmitRoutineOperatorCall(DType type, Expression targetExpr,
string routineFullName, string fallbackRoutineFullname, Expression routineNameExpr, CallSignature callSignature, AccessType access)
{
Debug.Assert(routineFullName != null ^ routineNameExpr != null);
MethodInfo operator_method;
PhpTypeCode return_type_code;
// (J) use call sites to call the method:
if (targetExpr != null /*|| type != null*/)
{
Debug.Assert(fallbackRoutineFullname == null);
return this.CallSitesBuilder.EmitMethodCall(this, CallSitesBuilder.AccessToReturnType(access), targetExpr, type, routineFullName, routineNameExpr, callSignature);
}
else if (targetExpr != null)
{
Debug.Assert(fallbackRoutineFullname == null);
// LOAD Operators.InvokeMethod(<target>, <method name>, <type desc>, <context>);
// start a new operators chain (as the rest of chain is read)
this.ChainBuilder.Create();
this.ChainBuilder.Begin();
this.ChainBuilder.Lengthen(); // for hop over ->
// prepare for operator invocation
this.EmitBoxing(targetExpr.Emit(this));
this.ChainBuilder.End();
this.EmitName(routineFullName, routineNameExpr, true);
this.EmitLoadClassContext();
this.EmitLoadScriptContext();
if (routineFullName != null)
operator_method = Methods.Operators.InvokeMethodStr;
else
operator_method = Methods.Operators.InvokeMethodObj;
return_type_code = PhpTypeCode.PhpReference;
}
else if (type != null)
{
Debug.Assert(fallbackRoutineFullname == null);
// LOAD Operators.InvokeStaticMethod(<type desc>, <method name>, <self>, <type desc>, context);
type.EmitLoadTypeDesc(this, ResolveTypeFlags.UseAutoload | ResolveTypeFlags.ThrowErrors);
this.EmitName(routineFullName, routineNameExpr, true);
this.EmitLoadSelf();
this.EmitLoadClassContext();
this.EmitLoadScriptContext();
operator_method = Methods.Operators.InvokeStaticMethod;
return_type_code = PhpTypeCode.PhpReference;
}
else
{
Debug.Assert(routineNameExpr == null || fallbackRoutineFullname == null); // (routineNameExpr != null) => (fallbackRoutineFullName == null)
// DRoutineDesc <callHint>;
FieldInfo hintField = this.CallSitesBuilder.DefineField(
"<callHint>'" + (routineFullName ?? "indirect"),
typeof(PHP.Core.Reflection.DRoutineDesc),
FieldAttributes.Static | FieldAttributes.Assembly);
// LOAD ScriptContext.Call{|Void|Value}(<local variables>, <naming context>, <function name>, ref <hint>, context);
this.EmitLoadRTVariablesTable();
this.EmitLoadNamingContext();
this.EmitName(routineFullName, routineNameExpr, true);
if (fallbackRoutineFullname != null) il.Emit(OpCodes.Ldstr, fallbackRoutineFullname); else il.Emit(OpCodes.Ldnull); // fallback fcn name
il.Emit(OpCodes.Ldsflda, hintField);
this.EmitLoadScriptContext();
// (J) only necessary copying, dereferencing or reference making:
if (access == AccessType.None)
{
operator_method = Methods.ScriptContext.CallVoid;
return_type_code = PhpTypeCode.Void;
}
else if (access == AccessType.Read)
{
operator_method = Methods.ScriptContext.CallValue;
return_type_code = PhpTypeCode.Object;
}
else
{
operator_method = Methods.ScriptContext.Call;
return_type_code = PhpTypeCode.PhpReference;
}
}
// emits load of parameters to the PHP stack:
callSignature.EmitLoadOnPhpStack(this);
// marks transient sequence point just before the call:
//.........这里部分代码省略.........
示例7: EmitEnsureStaticProperty
/// <summary>
/// Emits IL instructions that ensure that a static field is of <see cref="PhpObject"/> or <see cref="PhpArray"/>
/// type. Handles the case when field name is unknown at compile time (see <see cref="AST.IndirectStFldUse"/>).
/// </summary>
/// <param name="typeRef">The class name (identifier index).</param>
/// <param name="propertyName">The property name.</param>
/// <param name="propertyNameExpr">The expression that evaluates to property name.</param>
/// <param name="ensureArray">Whether to ensure that static field is an array (or an object).</param>
/// <remarks>
/// Nothing is expected on the evaluation stack. A <see cref="PhpArray"/> or <see cref="DObject"/> is left on the
/// evaluation stack.
/// </remarks>
public PhpTypeCode EmitEnsureStaticProperty(TypeRef typeRef, VariableName? propertyName,
Expression propertyNameExpr, bool ensureArray)
{
Debug.Assert(propertyName != null ^ propertyNameExpr != null);
ResolveTypeFlags flags = ResolveTypeFlags.UseAutoload | ResolveTypeFlags.ThrowErrors;
// LOAD Operators.EnsureStaticFieldIs[Object|Array](<type desc>, <field name>, <type desc>, <context>)
typeRef.EmitLoadTypeDesc(codeGenerator, flags);
if (propertyNameExpr != null)
codeGenerator.EmitBoxing(propertyNameExpr.Emit(codeGenerator));
else
codeGenerator.IL.Emit(OpCodes.Ldstr, propertyName.Value.ToString());
codeGenerator.EmitLoadClassContext();
codeGenerator.EmitLoadScriptContext();
if (ensureArray)
codeGenerator.IL.Emit(OpCodes.Call, Methods.Operators.EnsureStaticPropertyIsArray);
else
codeGenerator.IL.Emit(OpCodes.Call, Methods.Operators.EnsureStaticPropertyIsObject);
EmitErrorCheck(ensureArray);
return (ensureArray) ? PhpTypeCode.PhpArray : PhpTypeCode.DObject;
}
示例8: EmitEnsureItem
/// <summary>
/// Emits IL instructions that ensure that the specified item of specified array is of
/// type <see cref="PhpArray"/>.
/// </summary>
/// <param name="array">Array which item is examined.</param>
/// <param name="index">Index determining the item which should be examined (can be <B>null</B>).</param>
/// <param name="ensureArray">Whether to ensure that static field is an array (or an object).</param>
/// <remarks>
/// This method is used in operators chains. Nothing is expected on the evaluation stack.
/// If the item is of type <see cref="PhpArray"/> and <see cref="PhpObject"/> (respectively)
/// it is left on the evaluation stack. Otherwise the control is transfered to the end of chain.
/// </remarks>
public PhpTypeCode EmitEnsureItem(Expression/*!*/ array, Expression index, bool ensureArray)
{
if (!ensureArray) Lengthen();
array.Emit(codeGenerator);
if (index != null)
{
// keyed item:
Create();
codeGenerator.EmitBoxing(index.Emit(codeGenerator));
End();
if (ensureArray)
{
codeGenerator.IL.Emit(OpCodes.Callvirt, Methods.PhpArray.EnsureItemIsArray_Object);
}
else
{
codeGenerator.EmitLoadScriptContext();
codeGenerator.IL.Emit(OpCodes.Callvirt, Methods.PhpArray.EnsureItemIsObject_Object);
}
}
else
{
// key-less item:
if (ensureArray)
{
codeGenerator.IL.Emit(OpCodes.Callvirt, Methods.PhpArray.EnsureItemIsArray);
}
else
{
codeGenerator.EmitLoadScriptContext();
codeGenerator.IL.Emit(OpCodes.Callvirt, Methods.PhpArray.EnsureItemIsObject);
}
}
EmitErrorCheck(ensureArray);
return (ensureArray) ? PhpTypeCode.PhpArray : PhpTypeCode.DObject;
}
示例9: EmitUnsetItem
public void EmitUnsetItem(Expression array, Expression index)
{
// Template:
// void UnsetItem(object var,object index)
array.Emit(codeGenerator);
Debug.Assert(index != null);
Create();
codeGenerator.EmitBoxing(index.Emit(codeGenerator));
End();
codeGenerator.IL.Emit(OpCodes.Call, Methods.Operators.UnsetItem);
}
示例10: EmitGetItem
/// <summary>
/// Emits IL instructions that load the value of an item of given array.
/// </summary>
/// <param name="array"><see cref="Expression"/> determining the array.</param>
/// <param name="index"><see cref="Expression"/> determining the index whose value
/// should be obtained from the array.</param>
/// <param name="kind">A kind of getter.</param>
/// <remarks>Nothing is supposed on the evaluation stack. The value of the item is left
/// on the evaluation stack.</remarks>
public PhpTypeCode EmitGetItem(Expression/*!*/ array, Expression/*!*/ index, Operators.GetItemKinds kind)
{
ILEmitter il = codeGenerator.IL;
// array:
var arrayTypeCode = array.Emit(codeGenerator);
// ensure the array is writeable is required
if (EnsureWritable)
codeGenerator.EmitEnsureWritable(arrayTypeCode);
// index:
PhpTypeCode index_type_code = codeGenerator.EmitArrayKey(this, index);
// kind:
if (kind == Operators.GetItemKinds.Get && QuietRead)
kind = Operators.GetItemKinds.QuietGet;
il.LdcI4((int)kind);
// CALL Operators.GetItem(<array>, <index>, <kind>)
codeGenerator.EmitGetItem(index_type_code, index, false);
return PhpTypeCode.Object;
}
示例11: EmitGetArrayItemRef
public void EmitGetArrayItemRef(Expression/*!*/ array, Expression index)
{
array.Emit(codeGenerator);
PhpTypeCode index_type_code = PhpTypeCode.Invalid;
if (index != null)
index_type_code = codeGenerator.EmitArrayKey(this, index);
codeGenerator.EmitGetArrayItem(index_type_code, index, true);
}
示例12: EmitConcatExpressionLoad
/// <summary>
/// Emits load of an argument of a concatenation.
/// </summary>
private static PhpTypeCode EmitConcatExpressionLoad(CodeGenerator/*!*/ codeGenerator, Expression/*!*/ expression)
{
// tries to evaluate the expression:
if (expression.HasValue)
{
if (expression.Value is PhpBytes)
{
codeGenerator.IL.LoadLiteral(expression.Value);
return PhpTypeCode.PhpBytes;
}
else
{
// evaluated expression is converted to a string if necessary:
codeGenerator.IL.Emit(OpCodes.Ldstr, Convert.ObjectToString(expression.Value));
return PhpTypeCode.String;
}
}
else
{
// emits non-evaluable expression:
PhpTypeCode result = expression.Emit(codeGenerator);
// the result should be converted to string: (so we know the type for the further analysis)
if (result != PhpTypeCode.String && // string already
result != PhpTypeCode.Object && // object can contain PhpBytes, should be converted just when we know we need string
result != PhpTypeCode.PhpBytes // keep PhpBytes
)
{
codeGenerator.EmitBoxing(result); // in case of value-type
codeGenerator.IL.Emit(OpCodes.Call, Methods.Convert.ObjectToString);
result = PhpTypeCode.String;
}
return result;
}
}
示例13: EmitGetProperty
/// <summary>
/// Create and call <see cref="CallSite"/> for getting property.
/// </summary>
/// <param name="cg"><see cref="CodeGenerator"/>.</param>
/// <param name="wantRef">Wheter <see cref="PhpReference"/> is expected as the result.</param>
/// <param name="targetExpr">The expression representing the target (object).</param>
/// <param name="targetObjectPlace">The place representing the target (<see cref="DObject"/>) iff <paramref name="targetExpr"/> is not provided.</param>
/// <param name="targetPlace">The place representing the target (object) iff <paramref name="targetExpr"/> and <paramref name="targetObjectPlace"/> are not provided.</param>
/// <param name="targetType">Type of target iff we are getting property statically.</param>
/// <param name="fieldName">The name of the field. Can be null if the name is not known at compile time (indirect).</param>
/// <param name="fieldNameExpr">The expression used to get field name in run time (iff <paramref name="fieldName"/> is <c>null</c>.</param>
/// <param name="issetSemantics">Wheter we are only checking if the property exists. If true, no warnings are thrown during run time.</param>
/// <returns>Type code of the value that is pushed onto the top of the evaluation stack.</returns>
public PhpTypeCode EmitGetProperty(
PHP.Core.CodeGenerator/*!*/cg, bool wantRef,
Expression targetExpr, IPlace targetObjectPlace, IPlace targetPlace, DType targetType,
string fieldName, Expression fieldNameExpr,
bool issetSemantics)
{
Debug.Assert(fieldName != null ^ fieldNameExpr != null);
Debug.Assert(targetExpr != null || targetObjectPlace != null || targetPlace != null || targetType != null);
//
bool staticCall = (targetExpr == null && targetObjectPlace == null && targetPlace == null); // we are going to access static property
bool fieldNameIsKnown = (fieldName != null);
bool classContextIsKnown = (this.classContextPlace != null);
//
// binder flags:
//
Type returnType = wantRef ? Types.PhpReference[0] : Types.Object[0];
//
// define the call site:
//
//
List<Type> additionalArgs = new List<Type>();
if (!classContextIsKnown) additionalArgs.Add(Types.DTypeDesc[0]);
if (!fieldNameIsKnown) additionalArgs.Add(Types.String[0]);
var delegateTypeArgs = GetPropertyDelegateTypeArgs(
staticCall ? Types.DTypeDesc[0] : ((targetObjectPlace != null) ? Types.DObject[0] : Types.Object[0]), // DTypeDesc of static field's declaring type || DObject if field called on DObject known at compile time || otherwise object
additionalArgs.ToArray(),
returnType);
var delegateType = /*System.Linq.Expressions.Expression.*/delegateBuilder.GetDelegateType(delegateTypeArgs, callSitesCount); // (J) do not create dynamic delegates in dynamic modules, so they can be referenced from non-transient assemblies
//
var field = DefineCallSite(cg.IL, string.Format("get{0}_{1}", wantRef ? "ref" : string.Empty, fieldName ?? "$"), delegateType, (il) =>
{
// <LOAD> Binder.{GetProperty|GetStaticProperty}( fieldName, classContext, issetSemantics, <returnType> )
if (fieldName != null) il.Emit(OpCodes.Ldstr, fieldName); else il.Emit(OpCodes.Ldnull);
if (this.classContextPlace != null) this.classContextPlace.EmitLoad(il); else il.Emit(OpCodes.Ldsfld, Fields.UnknownTypeDesc.Singleton);
il.LoadBool(issetSemantics);
il.Emit(OpCodes.Ldtoken, returnType);
il.Emit(OpCodes.Call, Methods.GetTypeFromHandle);
il.Emit(OpCodes.Call, staticCall ? Methods.Binder.StaticGetProperty : Methods.Binder.GetProperty);
});
//
// call the CallSite:
//
// <field>.Target( <field>, <targetExpr|targetType>, (classContext)?, <methodNameExpr>? ):
cg.IL.Emit(OpCodes.Ldsfld, field);
cg.IL.Emit(OpCodes.Ldfld, field.FieldType.GetField("Target"));
cg.IL.Emit(OpCodes.Ldsfld, field);
if (staticCall) targetType.EmitLoadTypeDesc(cg, ResolveTypeFlags.UseAutoload | ResolveTypeFlags.ThrowErrors);
else if (targetExpr != null)
{
cg.ChainBuilder.Lengthen(); // for hop over ->
cg.EmitBoxing(targetExpr.Emit(cg)); // prepare for operator invocation
}
else if (targetObjectPlace != null) targetObjectPlace.EmitLoad(cg.IL);
else if (targetPlace != null) targetPlace.EmitLoad(cg.IL);
else Debug.Fail();
if (!classContextIsKnown) cg.EmitLoadClassContext();
if (!fieldNameIsKnown) cg.EmitName(fieldName/*null*/, fieldNameExpr, true, PhpTypeCode.String);
cg.MarkTransientSequencePoint();
cg.IL.Emit(OpCodes.Callvirt, delegateType.GetMethod("Invoke"));
cg.MarkTransientSequencePoint();
//
return PhpTypeCodeEnum.FromType(returnType);
}
示例14: EmitMethodTargetExpr
/// <summary>
/// Emit the target of instance method invocation.
/// </summary>
/// <param name="cg"></param>
/// <param name="targetExpr"></param>
private static void EmitMethodTargetExpr(PHP.Core.CodeGenerator/*!*/cg, Expression/*!*/targetExpr)
{
// start a new operators chain (as the rest of chain is read)
cg.ChainBuilder.Create();
cg.ChainBuilder.Begin();
cg.ChainBuilder.Lengthen(); // for hop over ->
// prepare for operator invocation
cg.EmitBoxing(targetExpr.Emit(cg));
cg.ChainBuilder.End();
}
示例15: EmitEmptyArrayStrictEquality
/// <summary>
/// Emits strict equality to empty PHP array.
/// </summary>
/// <param name="codeGenerator">A code generator.</param>
/// <param name="expr">Expression to be compared against.</param>
private static void EmitEmptyArrayStrictEquality(CodeGenerator/*!*/codeGenerator, Expression/*!*/expr)
{
if (IsEmptyArrayEx(expr))
{
// array() === array()
// LOAD true
codeGenerator.IL.LoadBool(true);
}
else if (expr is Literal)
{
// array() === NULL|int|double|string|...
// LOAD false
codeGenerator.IL.LoadBool(false);
}
else
{
// array() === <expr>
// LOAD <expr>
var exprTypeCode = expr.Emit(codeGenerator);
// check whether <expr> type can be an array
switch (exprTypeCode)
{
case PhpTypeCode.Boolean:
case PhpTypeCode.DObject:
case PhpTypeCode.Double:
case PhpTypeCode.Integer:
case PhpTypeCode.LongInteger:
case PhpTypeCode.PhpBytes:
case PhpTypeCode.PhpString:
case PhpTypeCode.String:
// always FALSE
codeGenerator.IL.Emit(OpCodes.Pop);
codeGenerator.IL.LoadBool(false);
break;
case PhpTypeCode.PhpArray:
// compare (PhpArray)<expr> with array()
codeGenerator.IL.Emit(OpCodes.Call, Methods.Operators.StrictEmptyPhpArrayEquality_PhpArray);
break;
default:
// compare <expr> with array()
codeGenerator.EmitBoxing(exprTypeCode);
codeGenerator.IL.Emit(OpCodes.Call, Methods.Operators.StrictEmptyPhpArrayEquality);
break;
}
}
}