private bool EmitExactStringKeyHash(PhpTypeCode keyTypeCode, Expression keyExpr) { if (keyExpr != null && keyTypeCode == PhpTypeCode.String && keyExpr.HasValue()) { string skey = (string)keyExpr.GetValue(); IntStringKey array_key = Convert.StringToArrayKey(skey); if (array_key.IsString && skey == array_key.String) // skey was not converted to int { il.LdcI4(array_key.GetHashCode()); // == array_key.Integer == IntStringKey.StringKeyToArrayIndex(skey) // previously: skey.GetHashCode() return true; } } return false; }
/// <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; }
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; }
/// <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; } } }