本文整理汇总了C#中Jurassic.Compiler.ILGenerator.ReleaseTemporaryVariable方法的典型用法代码示例。如果您正苦于以下问题:C# ILGenerator.ReleaseTemporaryVariable方法的具体用法?C# ILGenerator.ReleaseTemporaryVariable怎么用?C# ILGenerator.ReleaseTemporaryVariable使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Jurassic.Compiler.ILGenerator
的用法示例。
在下文中一共展示了ILGenerator.ReleaseTemporaryVariable方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: EmitDefaultValue
/// <summary>
/// Emits a default value of the given type.
/// </summary>
/// <param name="generator"> The IL generator. </param>
/// <param name="type"> The type of value to generate. </param>
public static void EmitDefaultValue(ILGenerator generator, Type type)
{
var temp = generator.CreateTemporaryVariable(type);
generator.LoadAddressOfVariable(temp);
generator.InitObject(temp.Type);
generator.LoadVariable(temp);
generator.ReleaseTemporaryVariable(temp);
}
示例2: GenerateCode
/// <summary>
/// Generates CIL for the statement.
/// </summary>
/// <param name="generator"> The generator to output the CIL to. </param>
/// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
{
// Generate code for the start of the statement.
var statementLocals = new StatementLocals() { NonDefaultBreakStatementBehavior = true };
GenerateStartOfStatement(generator, optimizationInfo, statementLocals);
// We need a label for each case clause and one for the default case.
var jumpTargets = new ILLabel[this.CaseClauses.Count];
int defaultIndex = -1;
ILLabel endOfSwitch = generator.CreateLabel();
// Generate code for the switch value.
var startOfSwitch = generator.CreateLabel();
this.Value.GenerateCode(generator, optimizationInfo);
EmitConversion.ToAny(generator, this.Value.ResultType);
// Save the switch value in a variable.
var switchValue = generator.CreateTemporaryVariable(typeof(object));
generator.StoreVariable(switchValue);
for (int i = 0; i < this.CaseClauses.Count; i ++)
{
var caseClause = this.CaseClauses[i];
// Create a label for each clause.
jumpTargets[i] = generator.CreateLabel();
if (caseClause.Value == null)
{
// This is a default clause.
defaultIndex = i;
continue;
}
// TypeComparer.StrictEquals(switchValue, caseValue)
generator.LoadVariable(switchValue);
caseClause.Value.GenerateCode(generator, optimizationInfo);
EmitConversion.ToAny(generator, caseClause.Value.ResultType);
generator.Call(ReflectionHelpers.TypeComparer_StrictEquals);
// if (TypeComparer.StrictEquals(switchValue, caseValue) == true)
// goto case i
generator.BranchIfTrue(jumpTargets[i]);
}
// None of the cases matched, jump to the default clause or the end of the switch.
if (defaultIndex >= 0)
generator.Branch(jumpTargets[defaultIndex]);
else
generator.Branch(endOfSwitch);
for (int i = 0; i < this.CaseClauses.Count; i++)
{
// Define a label at the start of the case clause.
generator.DefineLabelPosition(jumpTargets[i]);
// Set up the information needed by the break statement.
optimizationInfo.PushBreakOrContinueInfo(this.Labels, endOfSwitch, null, labelledOnly: false);
// Emit the case clause statements.
foreach (var statement in this.CaseClauses[i].BodyStatements)
statement.GenerateCode(generator, optimizationInfo);
// Revert the information needed by the break statement.
optimizationInfo.PopBreakOrContinueInfo();
}
// Define a label for the end of the switch statement.
generator.DefineLabelPosition(endOfSwitch);
// Release the switch value variable for use elsewhere.
generator.ReleaseTemporaryVariable(switchValue);
// Generate code for the end of the statement.
GenerateEndOfStatement(generator, optimizationInfo, statementLocals);
}
示例3: GenerateCode
/// <summary>
/// Generates CIL for the expression.
/// </summary>
/// <param name="generator"> The generator to output the CIL to. </param>
/// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
{
// Note: we use GetRawOperand() so that grouping operators are not ignored.
var operand = this.GetRawOperand(0);
// There is only one operand, and it can be either a reference or a function call.
// We need to split the operand into a function and some arguments.
// If the operand is a reference, it is equivalent to a function call with no arguments.
if (operand is FunctionCallExpression)
{
// Emit the function instance first.
var function = ((FunctionCallExpression)operand).Target;
function.GenerateCode(generator, optimizationInfo);
EmitConversion.ToAny(generator, function.ResultType);
}
else
{
// Emit the function instance first.
operand.GenerateCode(generator, optimizationInfo);
EmitConversion.ToAny(generator, operand.ResultType);
}
// Check the object really is a function - if not, throw an exception.
generator.IsInstance(typeof(Library.FunctionInstance));
generator.Duplicate();
var endOfTypeCheck = generator.CreateLabel();
generator.BranchIfNotNull(endOfTypeCheck);
// Throw an nicely formatted exception.
var targetValue = generator.CreateTemporaryVariable(typeof(object));
generator.StoreVariable(targetValue);
EmitHelpers.LoadScriptEngine(generator);
generator.LoadString("TypeError");
generator.LoadString("The new operator requires a function, found a '{0}' instead");
generator.LoadInt32(1);
generator.NewArray(typeof(object));
generator.Duplicate();
generator.LoadInt32(0);
generator.LoadVariable(targetValue);
generator.Call(ReflectionHelpers.TypeUtilities_TypeOf);
generator.StoreArrayElement(typeof(object));
generator.Call(ReflectionHelpers.String_Format);
generator.LoadInt32(optimizationInfo.SourceSpan.StartLine);
generator.LoadStringOrNull(optimizationInfo.Source.Path);
generator.LoadStringOrNull(optimizationInfo.FunctionName);
generator.NewObject(ReflectionHelpers.JavaScriptException_Constructor_Error);
generator.Throw();
generator.DefineLabelPosition(endOfTypeCheck);
generator.ReleaseTemporaryVariable(targetValue);
if (operand is FunctionCallExpression)
{
// Emit an array containing the function arguments.
((FunctionCallExpression)operand).GenerateArgumentsArray(generator, optimizationInfo);
}
else
{
// Emit an empty array.
generator.LoadInt32(0);
generator.NewArray(typeof(object));
}
// Call FunctionInstance.ConstructLateBound(argumentValues)
generator.Call(ReflectionHelpers.FunctionInstance_ConstructLateBound);
}
示例4: GenerateIncrementOrDecrement
/// <summary>
/// Generates CIL for an increment or decrement expression.
/// </summary>
/// <param name="generator"> The generator to output the CIL to. </param>
/// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
/// <param name="target"> The target to modify. </param>
/// <param name="postfix"> <c>true</c> if this is the postfix version of the operator;
/// <c>false</c> otherwise. </param>
/// <param name="increment"> <c>true</c> if this is the increment operator; <c>false</c> if
/// this is the decrement operator. </param>
private void GenerateIncrementOrDecrement(ILGenerator generator, OptimizationInfo optimizationInfo, IReferenceExpression target, bool postfix, bool increment)
{
// Note: increment and decrement can produce a number that is out of range if the
// target is of type Int32. The only time this should happen is for a loop variable
// where the range has been carefully checked to make sure an out of range condition
// cannot happen.
// Evaluate the left hand side only once.
target.GenerateReference(generator, optimizationInfo);
target.DuplicateReference(generator, optimizationInfo); // For the GenerateSet, later on.
// Get the target value.
target.GenerateGet(generator, optimizationInfo, true);
// Convert it to a number.
if (target.Type != PrimitiveType.Int32)
EmitConversion.ToNumber(generator, target.Type);
// If this is PostIncrement or PostDecrement, store the value so it can be returned later.
var result = generator.CreateTemporaryVariable(target.Type == PrimitiveType.Int32 ? PrimitiveType.Int32 : PrimitiveType.Number);
if (postfix == true)
{
generator.Duplicate();
generator.StoreVariable(result);
}
// Load the increment constant.
if (target.Type == PrimitiveType.Int32)
generator.LoadInt32(1);
else
generator.LoadDouble(1.0);
// Add or subtract the constant to the target value.
if (increment == true)
generator.Add();
else
generator.Subtract();
// If this is PreIncrement or PreDecrement, store the value so it can be returned later.
if (postfix == false)
{
generator.Duplicate();
generator.StoreVariable(result);
}
// Store the value.
target.GenerateSet(generator, optimizationInfo, target.Type == PrimitiveType.Int32 ? PrimitiveType.Int32 : PrimitiveType.Number, optimizationInfo.StrictMode);
// Restore the expression result.
generator.LoadVariable(result);
generator.ReleaseTemporaryVariable(result);
}
示例5: GenerateCompoundAssignment
/// <summary>
/// Generates CIL for a compound assignment expression.
/// </summary>
/// <param name="generator"> The generator to output the CIL to. </param>
/// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
/// <param name="target"> The target to modify. </param>
private void GenerateCompoundAssignment(ILGenerator generator, OptimizationInfo optimizationInfo, IReferenceExpression target)
{
// Evaluate the left hand side only once.
target.GenerateReference(generator, optimizationInfo);
target.DuplicateReference(generator, optimizationInfo); // For the GenerateSet, later on.
// Load the value to assign.
var compoundOperator = new BinaryExpression(GetCompoundBaseOperator(this.OperatorType), new ReferenceGetExpression(target), this.GetOperand(1));
compoundOperator.GenerateCode(generator, optimizationInfo);
// Store the resulting value so we can return it as the result of the expression.
var result = generator.CreateTemporaryVariable(compoundOperator.ResultType);
generator.Duplicate();
generator.StoreVariable(result);
// Store the value.
target.GenerateSet(generator, optimizationInfo, compoundOperator.ResultType, optimizationInfo.StrictMode);
// Restore the expression result.
generator.LoadVariable(result);
generator.ReleaseTemporaryVariable(result);
}
示例6: GenerateAssignment
/// <summary>
/// Generates CIL for an assignment expression.
/// </summary>
/// <param name="generator"> The generator to output the CIL to. </param>
/// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
/// <param name="target"> The target to modify. </param>
private void GenerateAssignment(ILGenerator generator, OptimizationInfo optimizationInfo, IReferenceExpression target)
{
// Evaluate the left hand side first!
target.GenerateReference(generator, optimizationInfo);
// Load the value to assign.
var rhs = this.GetOperand(1);
rhs.GenerateCode(generator, optimizationInfo);
// Support the inferred function displayName property.
if (rhs is FunctionExpression)
((FunctionExpression)rhs).GenerateDisplayName(generator, optimizationInfo, target.ToString(), false);
// Store the RHS value so we can return it as the result of the expression.
var result = generator.CreateTemporaryVariable(rhs.ResultType);
generator.Duplicate();
generator.StoreVariable(result);
// Store the value.
target.GenerateSet(generator, optimizationInfo, rhs.ResultType, optimizationInfo.StrictMode);
// Restore the RHS value.
generator.LoadVariable(result);
generator.ReleaseTemporaryVariable(result);
}
示例7: DuplicateReference
/// <summary>
/// Outputs the values needed to get or set this reference.
/// </summary>
/// <param name="generator"> The generator to output the CIL to. </param>
/// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
public void DuplicateReference(ILGenerator generator, OptimizationInfo optimizationInfo)
{
string propertyName = null;
TypeOfMemberAccess memberAccessType = DetermineTypeOfMemberAccess(optimizationInfo, out propertyName);
if (memberAccessType == TypeOfMemberAccess.ArrayIndex)
{
// Array indexer
var arg1 = generator.CreateTemporaryVariable(typeof(object));
var arg2 = generator.CreateTemporaryVariable(typeof(uint));
generator.StoreVariable(arg2);
generator.StoreVariable(arg1);
generator.LoadVariable(arg1);
generator.LoadVariable(arg2);
generator.LoadVariable(arg1);
generator.LoadVariable(arg2);
generator.ReleaseTemporaryVariable(arg1);
generator.ReleaseTemporaryVariable(arg2);
}
else if (memberAccessType == TypeOfMemberAccess.Static)
{
// Named property access
generator.Duplicate();
}
else
{
// Dynamic property access
var arg1 = generator.CreateTemporaryVariable(typeof(object));
var arg2 = generator.CreateTemporaryVariable(typeof(object));
generator.StoreVariable(arg2);
generator.StoreVariable(arg1);
generator.LoadVariable(arg1);
generator.LoadVariable(arg2);
generator.LoadVariable(arg1);
generator.LoadVariable(arg2);
generator.ReleaseTemporaryVariable(arg1);
generator.ReleaseTemporaryVariable(arg2);
}
}
示例8: GenerateSet
//.........这里部分代码省略.........
generator.LoadAddressOfVariable(cacheKey);
if (throwIfUnresolvable == false)
{
// Set the property value unconditionally.
generator.Call(ReflectionHelpers.ObjectInstance_InlineSetPropertyValue);
}
else
{
// Set the property value if the property exists.
generator.Call(ReflectionHelpers.ObjectInstance_InlineSetPropertyValueIfExists);
// The return value is true if the property was defined, and false if it wasn't.
generator.BranchIfTrue(endOfSet);
}
var endOfIf = generator.CreateLabel();
generator.Branch(endOfIf);
// else
generator.DefineLabelPosition(elseClause);
// object.InlinePropertyValues[__object_property_cachedIndex] = value;
generator.LoadVariable(objectInstance);
generator.Call(ReflectionHelpers.ObjectInstance_InlinePropertyValues);
generator.LoadVariable(cachedIndex);
generator.LoadVariable(value);
generator.StoreArrayElement(typeof(object));
generator.Branch(endOfSet);
// End of the if statement
generator.DefineLabelPosition(endOfIf);
}
else
{
// Slow route.
if (scopeVariable == null)
EmitHelpers.LoadScope(generator);
else
generator.LoadVariable(scopeVariable);
generator.CastClass(typeof(ObjectScope));
generator.Call(ReflectionHelpers.ObjectScope_ScopeObject);
generator.LoadString(this.Name);
generator.LoadVariable(value);
generator.LoadBoolean(optimizationInfo.StrictMode);
if (scope.ParentScope == null && throwIfUnresolvable == false)
{
// Set the property value unconditionally.
generator.Call(ReflectionHelpers.ObjectInstance_SetPropertyValue_Object);
}
else
{
// Set the property value if the property exists.
generator.Call(ReflectionHelpers.ObjectInstance_SetPropertyValueIfExists);
// The return value is true if the property was defined, and false if it wasn't.
generator.BranchIfTrue(endOfSet);
}
}
}
// Try the parent scope.
if (scope.ParentScope != null && scope.ExistsAtRuntime == true)
{
if (scopeVariable == null)
{
scopeVariable = generator.CreateTemporaryVariable(typeof(Scope));
EmitHelpers.LoadScope(generator);
}
else
{
generator.LoadVariable(scopeVariable);
}
generator.Call(ReflectionHelpers.Scope_ParentScope);
generator.StoreVariable(scopeVariable);
}
scope = scope.ParentScope;
} while (scope != null);
// The value might be still on top of the stack.
if (value == null && scope == null)
generator.Pop();
// Throw an error if the name does not exist and throwIfUnresolvable is true.
if (scope == null && throwIfUnresolvable == true)
EmitHelpers.EmitThrow(generator, ErrorType.ReferenceError, this.Name + " is not defined", optimizationInfo);
// Release the temporary variables.
if (value != null)
generator.ReleaseTemporaryVariable(value);
if (scopeVariable != null)
generator.ReleaseTemporaryVariable(scopeVariable);
// Define a label at the end.
generator.DefineLabelPosition(endOfSet);
}
示例9: GenerateIn
/// <summary>
/// Generates CIL for the in operator.
/// </summary>
/// <param name="generator"> The generator to output the CIL to. </param>
/// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
private void GenerateIn(ILGenerator generator, OptimizationInfo optimizationInfo)
{
// Emit the left-hand side expression and convert it to a string.
this.Left.GenerateCode(generator, optimizationInfo);
EmitConversion.ToString(generator, this.Left.ResultType);
// Store the left-hand side expression in a temporary variable.
var temp = generator.CreateTemporaryVariable(typeof(string));
generator.StoreVariable(temp);
// Emit the right-hand side expression.
this.Right.GenerateCode(generator, optimizationInfo);
EmitConversion.ToAny(generator, this.Right.ResultType);
// Check the right-hand side is a javascript object - if not, throw an exception.
generator.IsInstance(typeof(Library.ObjectInstance));
generator.Duplicate();
var endOfTypeCheck = generator.CreateLabel();
generator.BranchIfNotNull(endOfTypeCheck);
// Throw an nicely formatted exception.
var rightValue = generator.CreateTemporaryVariable(typeof(object));
generator.StoreVariable(rightValue);
EmitHelpers.LoadScriptEngine(generator);
generator.LoadString("TypeError");
generator.LoadString("The in operator expected an object, but found '{0}' instead");
generator.LoadInt32(1);
generator.NewArray(typeof(object));
generator.Duplicate();
generator.LoadInt32(0);
generator.LoadVariable(rightValue);
generator.Call(ReflectionHelpers.TypeUtilities_TypeOf);
generator.StoreArrayElement(typeof(object));
generator.Call(ReflectionHelpers.String_Format);
generator.LoadInt32(optimizationInfo.SourceSpan.StartLine);
generator.LoadStringOrNull(optimizationInfo.Source.Path);
generator.LoadStringOrNull(optimizationInfo.FunctionName);
generator.NewObject(ReflectionHelpers.JavaScriptException_Constructor_Error);
generator.Throw();
generator.DefineLabelPosition(endOfTypeCheck);
generator.ReleaseTemporaryVariable(rightValue);
// Load the left-hand side expression from the temporary variable.
generator.LoadVariable(temp);
// Call ObjectInstance.HasProperty(object)
generator.Call(ReflectionHelpers.ObjectInstance_HasProperty);
// Allow the temporary variable to be reused.
generator.ReleaseTemporaryVariable(temp);
}
示例10: GenerateStub
/// <summary>
/// Generates a method that does type conversion and calls the bound method.
/// </summary>
/// <param name="generator"> The ILGenerator used to output the body of the method. </param>
/// <param name="argumentCount"> The number of arguments that will be passed to the delegate. </param>
/// <returns> A delegate that does type conversion and calls the method represented by this
/// object. </returns>
protected override void GenerateStub(ILGenerator generator, int argumentCount)
{
// Here is what we are going to generate.
//private static object SampleBinder(ScriptEngine engine, object thisObject, object[] arguments)
//{
// // Target function signature: int (bool, int, string, object).
// bool param1;
// int param2;
// string param3;
// object param4;
// param1 = arguments[0] != 0;
// param2 = TypeConverter.ToInt32(arguments[1]);
// param3 = TypeConverter.ToString(arguments[2]);
// param4 = Undefined.Value;
// return thisObject.targetMethod(param1, param2, param3, param4);
//}
// Find the target method.
var binderMethod = this.buckets[Math.Min(argumentCount, this.buckets.Length - 1)];
// Constrain the number of apparent arguments to within the required bounds.
int minArgumentCount = binderMethod.RequiredParameterCount;
int maxArgumentCount = binderMethod.RequiredParameterCount + binderMethod.OptionalParameterCount;
if (binderMethod.HasParamArray == true)
maxArgumentCount = int.MaxValue;
foreach (var argument in binderMethod.GenerateArguments(generator, Math.Min(Math.Max(argumentCount, minArgumentCount), maxArgumentCount)))
{
switch (argument.Source)
{
case BinderArgumentSource.ScriptEngine:
// Load the "engine" parameter passed by the client.
generator.LoadArgument(0);
break;
case BinderArgumentSource.ThisValue:
// Load the "this" parameter passed by the client.
generator.LoadArgument(1);
bool inheritsFromObjectInstance = typeof(ObjectInstance).IsAssignableFrom(argument.Type);
if (argument.Type.IsClass == true && inheritsFromObjectInstance == false &&
argument.Type != typeof(string) && argument.Type != typeof(object))
{
// If the "this" object is an unsupported class, pass it through unmodified.
generator.CastClass(argument.Type);
}
else
{
if (argument.Type != typeof(object))
{
// If the target "this" object type is not of type object, throw an error if
// the value is undefined or null.
generator.Duplicate();
var temp = generator.CreateTemporaryVariable(typeof(object));
generator.StoreVariable(temp);
generator.LoadArgument(0);
generator.LoadVariable(temp);
generator.LoadString(binderMethod.Name);
generator.Call(ReflectionHelpers.TypeUtilities_VerifyThisObject);
generator.ReleaseTemporaryVariable(temp);
}
// Convert to the target type.
EmitTypeConversion(generator, typeof(object), argument.Type);
if (argument.Type != typeof(ObjectInstance) && inheritsFromObjectInstance == true)
{
// EmitConversionToObjectInstance can emit null if the toType is derived from ObjectInstance.
// Therefore, if the value emitted is null it means that the "thisObject" is a type derived
// from ObjectInstance (e.g. FunctionInstance) and the value provided is a different type
// (e.g. ArrayInstance). In this case, throw an exception explaining that the function is
// not generic.
var endOfThrowLabel = generator.CreateLabel();
generator.Duplicate();
generator.BranchIfNotNull(endOfThrowLabel);
generator.LoadArgument(0);
EmitHelpers.EmitThrow(generator, "TypeError", string.Format("The method '{0}' is not generic", binderMethod.Name));
generator.DefineLabelPosition(endOfThrowLabel);
}
}
break;
case BinderArgumentSource.InputParameter:
if (argument.InputParameterIndex < argumentCount)
{
// Load the argument onto the stack.
generator.LoadArgument(2);
generator.LoadInt32(argument.InputParameterIndex);
generator.LoadArrayElement(typeof(object));
// Get some flags that apply to the parameter.
var parameterFlags = JSParameterFlags.None;
var parameterAttribute = argument.GetCustomAttribute<JSParameterAttribute>();
//.........这里部分代码省略.........
示例11: ToObject
/// <summary>
/// Pops the value on the stack, converts it to a javascript object, then pushes the result
/// onto the stack.
/// </summary>
/// <param name="generator"> The IL generator. </param>
/// <param name="fromType"> The type to convert from. </param>
/// <param name="path"> The path of the javascript source file that is currently executing. </param>
/// <param name="function"> The name of the currently executing function. </param>
/// <param name="line"> The line number of the statement that is currently executing. </param>
public static void ToObject(ILGenerator generator, PrimitiveType fromType, string path, string function, int line)
{
// Check that a conversion is actually necessary.
if (fromType == PrimitiveType.Object)
return;
switch (fromType)
{
case PrimitiveType.Undefined:
// Converting from undefined always throws an exception.
EmitHelpers.EmitThrow(generator, ErrorType.TypeError, "Undefined cannot be converted to an object", path, function, line);
break;
case PrimitiveType.Null:
// Converting from null always throws an exception.
EmitHelpers.EmitThrow(generator, ErrorType.TypeError, "Null cannot be converted to an object", path, function, line);
break;
case PrimitiveType.Bool:
case PrimitiveType.Int32:
case PrimitiveType.UInt32:
case PrimitiveType.Number:
case PrimitiveType.String:
case PrimitiveType.ConcatenatedString:
case PrimitiveType.Any:
// Otherwise, fall back to calling TypeConverter.ToObject()
ToAny(generator, fromType);
var temp = generator.CreateTemporaryVariable(typeof(object));
generator.StoreVariable(temp);
EmitHelpers.LoadScriptEngine(generator);
generator.LoadVariable(temp);
generator.ReleaseTemporaryVariable(temp);
generator.LoadInt32(line);
generator.LoadStringOrNull(path);
generator.LoadStringOrNull(function);
generator.Call(ReflectionHelpers.TypeConverter_ToObject);
break;
default:
throw new NotImplementedException(string.Format("Unsupported primitive type: {0}", fromType));
}
}
示例12: ToInteger
/// <summary>
/// Pops the value on the stack, converts it to an integer, then pushes the integer result
/// onto the stack.
/// </summary>
/// <param name="generator"> The IL generator. </param>
/// <param name="fromType"> The type to convert from. </param>
public static void ToInteger(ILGenerator generator, PrimitiveType fromType)
{
// Check that a conversion is actually necessary.
if (fromType == PrimitiveType.Int32 || fromType == PrimitiveType.UInt32 || fromType == PrimitiveType.Bool)
return;
switch (fromType)
{
case PrimitiveType.Undefined:
case PrimitiveType.Null:
// Converting from undefined or null produces 0.
generator.Pop();
generator.LoadInt32(0);
break;
case PrimitiveType.Number:
// Converting from a number produces the following:
// Any number between -2147483648 and +2147483647 -> itself
// Any number smaller than -2147483648 -> -2147483648
// Any number larger than +2147483647 -> +2147483647
// NaN -> 0
// bool isPositiveInfinity = input > 2147483647.0
var isPositiveInfinity = generator.CreateTemporaryVariable(typeof(bool));
generator.Duplicate();
generator.LoadDouble(2147483647.0);
generator.CompareGreaterThan();
generator.StoreVariable(isPositiveInfinity);
// bool notNaN = input == input
var notNaN = generator.CreateTemporaryVariable(typeof(bool));
generator.Duplicate();
generator.Duplicate();
generator.CompareEqual();
generator.StoreVariable(notNaN);
// input = (int)input
// Infinity -> -2147483648
// -Infinity -> -2147483648
// NaN -> -2147483648
generator.ConvertToInteger();
// input = input & -((int)notNaN)
generator.LoadVariable(notNaN);
generator.Negate();
generator.BitwiseAnd();
// input = input - (int)isPositiveInfinity
generator.LoadVariable(isPositiveInfinity);
generator.Subtract();
// The temporary variables are no longer needed.
generator.ReleaseTemporaryVariable(notNaN);
generator.ReleaseTemporaryVariable(isPositiveInfinity);
break;
case PrimitiveType.String:
case PrimitiveType.ConcatenatedString:
case PrimitiveType.Any:
case PrimitiveType.Object:
// Otherwise, fall back to calling TypeConverter.ToInteger()
generator.Call(ReflectionHelpers.TypeConverter_ToInteger);
break;
default:
throw new NotImplementedException(string.Format("Unsupported primitive type: {0}", fromType));
}
}
示例13: ToBool
/// <summary>
/// Pops the value on the stack, converts it to a boolean, then pushes the boolean result
/// onto the stack.
/// </summary>
/// <param name="generator"> The IL generator. </param>
/// <param name="fromType"> The type to convert from. </param>
public static void ToBool(ILGenerator generator, PrimitiveType fromType)
{
// Check that a conversion is actually necessary.
if (fromType == PrimitiveType.Bool)
return;
switch (fromType)
{
case PrimitiveType.Undefined:
case PrimitiveType.Null:
// Converting from undefined or null produces false.
generator.Pop();
generator.LoadInt32(0);
break;
case PrimitiveType.Int32:
case PrimitiveType.UInt32:
// Converting from an integer produces true if the integer is non-zero.
generator.LoadInt32(0);
generator.CompareGreaterThanUnsigned();
break;
case PrimitiveType.Number:
// Converting from a number produces true if the number is non-zero and not NaN.
var temp = generator.CreateTemporaryVariable(fromType);
generator.StoreVariable(temp);
// input != 0
generator.LoadVariable(temp);
generator.LoadDouble(0.0);
generator.CompareEqual();
generator.LoadInt32(0);
generator.CompareEqual();
// input == input
generator.LoadVariable(temp);
generator.Duplicate();
generator.CompareEqual();
// &&
generator.CompareEqual();
// The temporary variable is no longer needed.
generator.ReleaseTemporaryVariable(temp);
break;
case PrimitiveType.String:
// Converting from a string produces true if the string is not empty.
generator.Call(ReflectionHelpers.String_Length);
generator.LoadInt32(0);
generator.CompareGreaterThan();
break;
case PrimitiveType.ConcatenatedString:
// Converting from a string produces true if the string is not empty.
generator.Call(ReflectionHelpers.ConcatenatedString_Length);
generator.LoadInt32(0);
generator.CompareGreaterThan();
break;
case PrimitiveType.Any:
case PrimitiveType.Object:
// Otherwise, fall back to calling TypeConverter.ToBoolean()
generator.Call(ReflectionHelpers.TypeConverter_ToBoolean);
break;
default:
throw new NotImplementedException(string.Format("Unsupported primitive type: {0}", fromType));
}
}
示例14: GenerateCode
/// <summary>
/// Generates CIL for the expression.
/// </summary>
/// <param name="generator"> The generator to output the CIL to. </param>
/// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
{
// Check if this is a direct call to eval().
if (this.Target is NameExpression && ((NameExpression)this.Target).Name == "eval")
{
GenerateEval(generator, optimizationInfo);
return;
}
// Emit the function instance first.
ILLocalVariable targetBase = null;
if (this.Target is MemberAccessExpression)
{
// The function is a member access expression (e.g. "Math.cos()").
// Evaluate the left part of the member access expression.
var baseExpression = ((MemberAccessExpression)this.Target).Base;
baseExpression.GenerateCode(generator, optimizationInfo);
EmitConversion.ToAny(generator, baseExpression.ResultType);
targetBase = generator.CreateTemporaryVariable(typeof(object));
generator.StoreVariable(targetBase);
// Evaluate the right part of the member access expression.
var memberAccessExpression = new MemberAccessExpression(((MemberAccessExpression)this.Target).Operator);
memberAccessExpression.Push(new TemporaryVariableExpression(targetBase));
memberAccessExpression.Push(((MemberAccessExpression)this.Target).GetOperand(1));
memberAccessExpression.GenerateCode(generator, optimizationInfo);
EmitConversion.ToAny(generator, this.Target.ResultType);
}
else
{
// Something else (e.g. "eval()").
this.Target.GenerateCode(generator, optimizationInfo);
EmitConversion.ToAny(generator, this.Target.ResultType);
}
// Check the object really is a function - if not, throw an exception.
generator.IsInstance(typeof(Library.FunctionInstance));
generator.Duplicate();
var endOfTypeCheck = generator.CreateLabel();
generator.BranchIfNotNull(endOfTypeCheck);
// Throw an nicely formatted exception.
generator.Pop();
EmitHelpers.EmitThrow(generator, "TypeError", string.Format("'{0}' is not a function", this.Target.ToString()));
generator.DefineLabelPosition(endOfTypeCheck);
// Pass in the path, function name and line.
generator.LoadStringOrNull(optimizationInfo.Source.Path);
generator.LoadStringOrNull(optimizationInfo.FunctionName);
generator.LoadInt32(optimizationInfo.SourceSpan.StartLine);
// Generate code to produce the "this" value. There are three cases.
if (this.Target is NameExpression)
{
// 1. The function is a name expression (e.g. "parseInt()").
// In this case this = scope.ImplicitThisValue, if there is one, otherwise undefined.
((NameExpression)this.Target).GenerateThis(generator);
}
else if (this.Target is MemberAccessExpression)
{
// 2. The function is a member access expression (e.g. "Math.cos()").
// In this case this = Math.
//var baseExpression = ((MemberAccessExpression)this.Target).Base;
//baseExpression.GenerateCode(generator, optimizationInfo);
//EmitConversion.ToAny(generator, baseExpression.ResultType);
generator.LoadVariable(targetBase);
}
else
{
// 3. Neither of the above (e.g. "(function() { return 5 })()")
// In this case this = undefined.
EmitHelpers.EmitUndefined(generator);
}
// Emit an array containing the function arguments.
GenerateArgumentsArray(generator, optimizationInfo);
// Call FunctionInstance.CallLateBound(thisValue, argumentValues)
generator.Call(ReflectionHelpers.FunctionInstance_CallWithStackTrace);
// Allow reuse of the temporary variable.
if (targetBase != null)
generator.ReleaseTemporaryVariable(targetBase);
}
示例15: EmitConversionToObject
/// <summary>
/// Pops the value on the stack, converts it to an object, then pushes the result onto the
/// stack.
/// </summary>
/// <param name="generator"> The IL generator. </param>
/// <param name="fromType"> The type to convert from. </param>
internal static void EmitConversionToObject(ILGenerator generator, Type fromType)
{
// If the from type is a reference type, check for null.
ILLabel endOfNullCheck = null;
if (fromType.IsValueType == false)
{
var startOfElse = generator.CreateLabel();
endOfNullCheck = generator.CreateLabel();
generator.Duplicate();
generator.BranchIfNotNull(startOfElse);
generator.Pop();
EmitHelpers.EmitNull(generator);
generator.Branch(endOfNullCheck);
generator.DefineLabelPosition(startOfElse);
}
switch (Type.GetTypeCode(fromType))
{
case TypeCode.Boolean:
generator.Box(typeof(bool));
break;
case TypeCode.Byte:
generator.Box(typeof(int));
break;
case TypeCode.Char:
generator.LoadInt32(1);
generator.NewObject(ReflectionHelpers.String_Constructor_Char_Int);
break;
case TypeCode.DBNull:
throw new NotSupportedException("DBNull is not a supported return type.");
case TypeCode.Decimal:
generator.Call(ReflectionHelpers.Decimal_ToDouble);
generator.Box(typeof(double));
break;
case TypeCode.Double:
generator.Box(typeof(double));
break;
case TypeCode.Empty:
throw new NotSupportedException("Empty is not a supported return type.");
case TypeCode.Int16:
generator.Box(typeof(int));
break;
case TypeCode.Int32:
generator.Box(typeof(int));
break;
case TypeCode.Int64:
generator.ConvertToDouble();
generator.Box(typeof(double));
break;
case TypeCode.DateTime:
case TypeCode.Object:
// Check if the type must be wrapped with a ClrInstanceWrapper.
// Note: if the type is a value type it cannot be a primitive or it would
// have been handled elsewhere in the switch.
ILLabel endOfWrapCheck = null;
if (fromType.IsValueType == false)
{
generator.Duplicate();
generator.Call(ReflectionHelpers.TypeUtilities_IsPrimitiveOrObject);
endOfWrapCheck = generator.CreateLabel();
generator.BranchIfTrue(endOfWrapCheck);
}
// The type must be wrapped.
var temp = generator.CreateTemporaryVariable(fromType);
generator.StoreVariable(temp);
generator.LoadArgument(0);
generator.LoadVariable(temp);
if (fromType.IsValueType == true)
generator.Box(fromType);
generator.ReleaseTemporaryVariable(temp);
generator.NewObject(ReflectionHelpers.ClrInstanceWrapper_Constructor);
// End of wrap check.
if (fromType.IsValueType == false)
generator.DefineLabelPosition(endOfWrapCheck);
break;
case TypeCode.SByte:
generator.Box(typeof(int));
break;
case TypeCode.Single:
generator.Box(typeof(double));
break;
case TypeCode.String:
break;
case TypeCode.UInt16:
generator.Box(typeof(int));
break;
case TypeCode.UInt32:
generator.Box(typeof(uint));
break;
//.........这里部分代码省略.........