本文整理汇总了C#中Jurassic.Compiler.ILGenerator.Duplicate方法的典型用法代码示例。如果您正苦于以下问题:C# ILGenerator.Duplicate方法的具体用法?C# ILGenerator.Duplicate怎么用?C# ILGenerator.Duplicate使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Jurassic.Compiler.ILGenerator
的用法示例。
在下文中一共展示了ILGenerator.Duplicate方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: 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);
}
}
示例2: GenerateDelete
/// <summary>
/// Deletes the reference and pushes <c>true</c> if the delete succeeded, or <c>false</c>
/// if the delete failed.
/// </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 GenerateDelete(ILGenerator generator, OptimizationInfo optimizationInfo)
{
// Deleting a variable is not allowed in strict mode.
if (optimizationInfo.StrictMode == true)
throw new JavaScriptException(optimizationInfo.Engine, ErrorType.SyntaxError, string.Format("Cannot delete {0} because deleting a variable or argument is not allowed in strict mode", this.Name), optimizationInfo.SourceSpan.StartLine, optimizationInfo.Source.Path, optimizationInfo.FunctionName);
var endOfDelete = generator.CreateLabel();
var scope = this.Scope;
ILLocalVariable scopeVariable = generator.CreateTemporaryVariable(typeof(Scope));
EmitHelpers.LoadScope(generator);
generator.StoreVariable(scopeVariable);
do
{
if (scope is DeclarativeScope)
{
var variable = scope.GetDeclaredVariable(this.Name);
if (variable != null)
{
// The variable is known at compile-time.
if (variable.Deletable == false)
{
// The variable cannot be deleted - return false.
generator.LoadBoolean(false);
}
else
{
// The variable can be deleted (it was declared inside an eval()).
// Delete the variable.
generator.LoadVariable(scopeVariable);
generator.CastClass(typeof(DeclarativeScope));
generator.LoadString(this.Name);
generator.Call(ReflectionHelpers.Scope_Delete);
}
break;
}
else
{
// The variable was not defined at compile time, but may have been
// introduced by an eval() statement.
if (optimizationInfo.MethodOptimizationHints.HasEval == true)
{
// Check the variable exists: if (scope.HasValue(variableName) == true) {
generator.LoadVariable(scopeVariable);
generator.CastClass(typeof(DeclarativeScope));
generator.LoadString(this.Name);
generator.Call(ReflectionHelpers.Scope_HasValue);
var hasValueClause = generator.CreateLabel();
generator.BranchIfFalse(hasValueClause);
// If the variable does exist, return true.
generator.LoadVariable(scopeVariable);
generator.CastClass(typeof(DeclarativeScope));
generator.LoadString(this.Name);
generator.Call(ReflectionHelpers.Scope_Delete);
generator.Branch(endOfDelete);
// }
generator.DefineLabelPosition(hasValueClause);
}
}
}
else
{
// Check if the property exists by calling scope.ScopeObject.HasProperty(propertyName)
generator.LoadVariable(scopeVariable);
generator.CastClass(typeof(ObjectScope));
generator.Call(ReflectionHelpers.ObjectScope_ScopeObject);
generator.Duplicate();
generator.LoadString(this.Name);
generator.Call(ReflectionHelpers.ObjectInstance_HasProperty);
// Jump past the delete if the property doesn't exist.
var endOfExistsCheck = generator.CreateLabel();
generator.BranchIfFalse(endOfExistsCheck);
// Call scope.ScopeObject.Delete(key, false)
generator.LoadString(this.Name);
generator.LoadBoolean(false);
generator.Call(ReflectionHelpers.ObjectInstance_Delete);
generator.Branch(endOfDelete);
generator.DefineLabelPosition(endOfExistsCheck);
generator.Pop();
// If the name is not defined, return true.
if (scope.ParentScope == null)
{
generator.LoadBoolean(true);
}
}
// Try the parent scope.
if (scope.ParentScope != null && scope.ExistsAtRuntime == true)
{
//.........这里部分代码省略.........
示例3: GenerateThis
/// <summary>
/// Generates code to push the "this" value for a function call.
/// </summary>
/// <param name="generator"> The generator to output the CIL to. </param>
public void GenerateThis(ILGenerator generator)
{
// Optimization: if there are no with scopes, simply emit undefined.
bool scopeChainHasWithScope = false;
var scope = this.Scope;
do
{
if (scope is ObjectScope && ((ObjectScope)scope).ProvidesImplicitThisValue == true)
{
scopeChainHasWithScope = true;
break;
}
scope = scope.ParentScope;
} while (scope != null);
if (scopeChainHasWithScope == false)
{
// No with scopes in the scope chain, use undefined as the "this" value.
EmitHelpers.EmitUndefined(generator);
return;
}
var end = generator.CreateLabel();
scope = this.Scope;
ILLocalVariable scopeVariable = generator.CreateTemporaryVariable(typeof(Scope));
EmitHelpers.LoadScope(generator);
generator.StoreVariable(scopeVariable);
do
{
if (scope is DeclarativeScope)
{
if (scope.HasDeclaredVariable(this.Name))
{
// The variable exists but declarative scopes always produce undefined for
// the "this" value.
EmitHelpers.EmitUndefined(generator);
break;
}
}
else
{
var objectScope = (ObjectScope)scope;
// Check if the property exists by calling scope.ScopeObject.HasProperty(propertyName)
if (objectScope.ProvidesImplicitThisValue == false)
EmitHelpers.EmitUndefined(generator);
generator.LoadVariable(scopeVariable);
generator.CastClass(typeof(ObjectScope));
generator.Call(ReflectionHelpers.ObjectScope_ScopeObject);
if (objectScope.ProvidesImplicitThisValue == true)
generator.Duplicate();
generator.LoadString(this.Name);
generator.Call(ReflectionHelpers.ObjectInstance_HasProperty);
generator.BranchIfTrue(end);
generator.Pop();
// If the name is not defined, use undefined for the "this" value.
if (scope.ParentScope == null)
{
EmitHelpers.EmitUndefined(generator);
}
}
// Try the parent scope.
if (scope.ParentScope != null && scope.ExistsAtRuntime == true)
{
generator.LoadVariable(scopeVariable);
generator.Call(ReflectionHelpers.Scope_ParentScope);
generator.StoreVariable(scopeVariable);
}
scope = scope.ParentScope;
} while (scope != null);
// Release the temporary variable.
generator.ReleaseTemporaryVariable(scopeVariable);
// Define a label at the end.
generator.DefineLabelPosition(end);
}
示例4: GenerateDisplayName
/// <summary>
/// Generates CIL to set the display name of the function. The function should be on top of the stack.
/// </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="displayName"> The display name of the function. </param>
/// <param name="force"> <c>true</c> to set the displayName property, even if the function has a name already. </param>
public void GenerateDisplayName(ILGenerator generator, OptimizationInfo optimizationInfo, string displayName, bool force)
{
if (displayName == null)
throw new ArgumentNullException("displayName");
// We only infer names for functions if the function doesn't have a name.
if (force == true || string.IsNullOrEmpty(this.FunctionName))
{
// Statically set the display name.
this.context.DisplayName = displayName;
// Generate code to set the display name at runtime.
generator.Duplicate();
generator.LoadString("displayName");
generator.LoadString(displayName);
generator.LoadBoolean(false);
generator.Call(ReflectionHelpers.ObjectInstance_SetPropertyValue_String);
}
}
示例5: 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);
}
示例6: 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);
}
示例7: 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);
}
示例8: GenerateTemplateArgumentsArray
/// <summary>
/// Generates an array containing the argument values for a tagged template literal.
/// </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="templateLiteral"> The template literal expression containing the parameter
/// values. </param>
internal void GenerateTemplateArgumentsArray(ILGenerator generator, OptimizationInfo optimizationInfo, TemplateLiteralExpression templateLiteral)
{
// Generate an array containing the value of each argument.
generator.LoadInt32(templateLiteral.Values.Count + 1);
generator.NewArray(typeof(object));
// Load the first parameter.
generator.Duplicate();
generator.LoadInt32(0);
// The first parameter to the tag function is an array of strings.
var stringsExpression = new List<Expression>(templateLiteral.Strings.Count);
foreach (var templateString in templateLiteral.Strings)
{
stringsExpression.Add(new LiteralExpression(templateString));
}
new LiteralExpression(stringsExpression).GenerateCode(generator, optimizationInfo);
generator.Duplicate();
// Now we need the name of the property.
generator.LoadString("raw");
// Now generate an array of raw strings.
var rawStringsExpression = new List<Expression>(templateLiteral.RawStrings.Count);
foreach (var rawString in templateLiteral.RawStrings)
{
rawStringsExpression.Add(new LiteralExpression(rawString));
}
new LiteralExpression(rawStringsExpression).GenerateCode(generator, optimizationInfo);
// Freeze array by calling ObjectInstance Freeze(ObjectInstance).
generator.CallStatic(ReflectionHelpers.ObjectConstructor_Freeze);
// Now store the raw strings as a property of the base strings array.
generator.LoadBoolean(optimizationInfo.StrictMode);
generator.Call(ReflectionHelpers.ObjectInstance_SetPropertyValue_Object);
// Freeze array by calling ObjectInstance Freeze(ObjectInstance).
generator.CallStatic(ReflectionHelpers.ObjectConstructor_Freeze);
// Store in the array.
generator.StoreArrayElement(typeof(object));
// Values are passed as subsequent parameters.
for (int i = 0; i < templateLiteral.Values.Count; i++)
{
generator.Duplicate();
generator.LoadInt32(i + 1);
templateLiteral.Values[i].GenerateCode(generator, optimizationInfo);
EmitConversion.ToAny(generator, templateLiteral.Values[i].ResultType);
generator.StoreArrayElement(typeof(object));
}
}
示例9: GenerateArgumentsArray
/// <summary>
/// Generates an array containing the argument values.
/// </summary>
/// <param name="generator"> The generator to output the CIL to. </param>
/// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
internal void GenerateArgumentsArray(ILGenerator generator, OptimizationInfo optimizationInfo)
{
// Emit the arguments. The arguments operand can be non-existant, a single expression,
// or a comma-delimited list.
if (this.OperandCount < 2)
{
// No parameters passed. Create an empty array.
generator.LoadInt32(0);
generator.NewArray(typeof(object));
}
else
{
// One or more arguments.
IList<Expression> arguments;
var argumentsOperand = this.GetRawOperand(1);
if (argumentsOperand is ListExpression)
{
// Multiple parameters were passed to the function.
arguments = ((ListExpression)argumentsOperand).Items;
}
else
{
// A single parameter was passed to the function.
arguments = new List<Expression>(1) { argumentsOperand };
}
// Generate an array containing the value of each argument.
generator.LoadInt32(arguments.Count);
generator.NewArray(typeof(object));
for (int i = 0; i < arguments.Count; i++)
{
generator.Duplicate();
generator.LoadInt32(i);
arguments[i].GenerateCode(generator, optimizationInfo);
EmitConversion.ToAny(generator, arguments[i].ResultType);
generator.StoreArrayElement(typeof(object));
}
}
}
示例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)
{
// Determine the methods that have the correct number of arguments.
var candidateMethods = new List<BinderMethod>();
foreach (var candidateMethod in this.targetMethods)
{
if (candidateMethod.IsArgumentCountCompatible(argumentCount) == true)
candidateMethods.Add(candidateMethod);
}
// Zero candidates means no overload had the correct number of arguments.
if (candidateMethods.Count == 0)
{
EmitHelpers.EmitThrow(generator, "TypeError", string.Format("No overload for method '{0}' takes {1} arguments", this.Name, argumentCount));
EmitHelpers.EmitDefaultValue(generator, PrimitiveType.Any);
generator.Complete();
return;
}
// Select the method to call at run time.
generator.LoadInt32(candidateMethods.Count);
generator.NewArray(typeof(RuntimeMethodHandle));
for (int i = 0; i < candidateMethods.Count; i ++)
{
generator.Duplicate();
generator.LoadInt32(i);
generator.LoadToken(candidateMethods[i]);
generator.StoreArrayElement(typeof(RuntimeMethodHandle));
}
generator.LoadArgument(0);
generator.LoadArgument(1);
generator.LoadArgument(2);
generator.Call(ReflectionHelpers.BinderUtilities_ResolveOverloads);
var endOfMethod = generator.CreateLabel();
for (int i = 0; i < candidateMethods.Count; i++)
{
// Check if this is the selected method.
ILLabel endOfIf = null;
if (i < candidateMethods.Count - 1)
{
generator.Duplicate();
generator.LoadInt32(i);
endOfIf = generator.CreateLabel();
generator.BranchIfNotEqual(endOfIf);
}
generator.Pop();
var targetMethod = candidateMethods[i];
// Convert the arguments.
foreach (var argument in targetMethod.GenerateArguments(generator, argumentCount))
{
// Load the input parameter value.
switch (argument.Source)
{
case BinderArgumentSource.ScriptEngine:
generator.LoadArgument(0);
break;
case BinderArgumentSource.ThisValue:
generator.LoadArgument(1);
break;
case BinderArgumentSource.InputParameter:
generator.LoadArgument(2);
generator.LoadInt32(argument.InputParameterIndex);
generator.LoadArrayElement(typeof(object));
break;
}
// Convert to the target type.
EmitConversionToType(generator, argument.Type, convertToAddress: argument.Source == BinderArgumentSource.ThisValue);
}
// Call the target method.
targetMethod.GenerateCall(generator);
// Convert the return value.
if (targetMethod.ReturnType == typeof(void))
EmitHelpers.EmitUndefined(generator);
else
EmitConversionToObject(generator, targetMethod.ReturnType);
// Branch to the end of the method if this was the selected method.
if (endOfIf != null)
{
generator.Branch(endOfMethod);
generator.DefineLabelPosition(endOfIf);
}
}
generator.DefineLabelPosition(endOfMethod);
generator.Complete();
}
示例11: 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)
{
// This code is only used for untagged template literals.
// Tagged template literals are handled by FunctionCallExpression.
// Load the values array onto the stack.
generator.LoadInt32(this.Strings.Count + this.Values.Count);
generator.NewArray(typeof(string));
for (int i = 0; i < this.Strings.Count; i++)
{
// Operands for StoreArrayElement() are: an array (string[]), index (int), value (string).
// Store the string.
generator.Duplicate();
generator.LoadInt32(i * 2);
generator.LoadString(this.Strings[i]);
generator.StoreArrayElement(typeof(string));
if (i == this.Strings.Count - 1)
break;
// Store the value.
generator.Duplicate();
generator.LoadInt32(i * 2 + 1);
this.Values[i].GenerateCode(generator, optimizationInfo);
EmitConversion.ToString(generator, this.Values[i].ResultType);
generator.StoreArrayElement(typeof(string));
}
// Call String.Concat(string[])
generator.CallStatic(ReflectionHelpers.String_Concat);
}
示例12: 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;
//.........这里部分代码省略.........
示例13: EmitConversionToType
/// <summary>
/// Pops the value on the stack, converts it from an object to the given type, then pushes
/// the result onto the stack.
/// </summary>
/// <param name="generator"> The IL generator. </param>
/// <param name="toType"> The type to convert to. </param>
/// <param name="convertToAddress"> <c>true</c> if the value is intended for use as an
/// instance pointer; <c>false</c> otherwise. </param>
internal static void EmitConversionToType(ILGenerator generator, Type toType, bool convertToAddress)
{
// Convert Null.Value to null if the target type is a reference type.
ILLabel endOfNullCheck = null;
if (toType.IsValueType == false)
{
var startOfElse = generator.CreateLabel();
endOfNullCheck = generator.CreateLabel();
generator.Duplicate();
EmitHelpers.EmitNull(generator);
generator.BranchIfNotEqual(startOfElse);
generator.Pop();
generator.LoadNull();
generator.Branch(endOfNullCheck);
generator.DefineLabelPosition(startOfElse);
}
switch (Type.GetTypeCode(toType))
{
case TypeCode.Boolean:
EmitConversion.ToBool(generator, PrimitiveType.Any);
break;
case TypeCode.Byte:
EmitConversion.ToInt32(generator, PrimitiveType.Any);
break;
case TypeCode.Char:
EmitConversion.ToString(generator, PrimitiveType.Any);
generator.Duplicate();
generator.Call(ReflectionHelpers.String_Length);
generator.LoadInt32(1);
var endOfCharCheck = generator.CreateLabel();
generator.BranchIfEqual(endOfCharCheck);
EmitHelpers.EmitThrow(generator, "TypeError", "Cannot convert string to char - the string must be exactly one character long");
generator.DefineLabelPosition(endOfCharCheck);
generator.LoadInt32(0);
generator.Call(ReflectionHelpers.String_GetChars);
break;
case TypeCode.DBNull:
throw new NotSupportedException("DBNull is not a supported parameter type.");
case TypeCode.Decimal:
EmitConversion.ToNumber(generator, PrimitiveType.Any);
generator.NewObject(ReflectionHelpers.Decimal_Constructor_Double);
break;
case TypeCode.Double:
EmitConversion.ToNumber(generator, PrimitiveType.Any);
break;
case TypeCode.Empty:
throw new NotSupportedException("Empty is not a supported return type.");
case TypeCode.Int16:
EmitConversion.ToInt32(generator, PrimitiveType.Any);
break;
case TypeCode.Int32:
EmitConversion.ToInt32(generator, PrimitiveType.Any);
break;
case TypeCode.Int64:
EmitConversion.ToNumber(generator, PrimitiveType.Any);
generator.ConvertToInt64();
break;
case TypeCode.DateTime:
case TypeCode.Object:
// Check if the type must be unwrapped.
generator.Duplicate();
generator.IsInstance(typeof(Jurassic.Library.ClrInstanceWrapper));
var endOfUnwrapCheck = generator.CreateLabel();
generator.BranchIfFalse(endOfUnwrapCheck);
// Unwrap the wrapped instance.
generator.Call(ReflectionHelpers.ClrInstanceWrapper_GetWrappedInstance);
generator.DefineLabelPosition(endOfUnwrapCheck);
// Value types must be unboxed.
if (toType.IsValueType == true)
{
if (convertToAddress == true)
// Unbox.
generator.Unbox(toType);
else
// Unbox and copy to the stack.
generator.UnboxAny(toType);
//// Calling methods on value required the address of the value type, not the value type itself.
//if (argument.Source == BinderArgumentSource.ThisValue && argument.Type.IsValueType == true)
//{
// var temp = generator.CreateTemporaryVariable(argument.Type);
// generator.StoreVariable(temp);
// generator.LoadAddressOfVariable(temp);
// generator.ReleaseTemporaryVariable(temp);
//}
}
//.........这里部分代码省略.........
示例14: 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, NonDefaultSourceSpanBehavior = true };
GenerateStartOfStatement(generator, optimizationInfo, statementLocals);
// Construct a loop expression.
// var iterator = TypeUtilities.GetIterator(obj);
// while (true) {
// continue-target:
// if (enumerator.MoveNext() == false)
// goto break-target;
// lhs = enumerator.Current;
//
// <body statements>
// }
// break-target:
// Call: ObjectInstance GetIterator(ScriptEngine engine, ObjectInstance iterable)
// Then call: IEnumerable<object> Iterate(ScriptEngine engine, ObjectInstance iterator)
optimizationInfo.MarkSequencePoint(generator, this.TargetObjectSourceSpan);
EmitHelpers.LoadScriptEngine(generator);
generator.Duplicate();
this.TargetObject.GenerateCode(generator, optimizationInfo);
EmitConversion.ToObject(generator, this.TargetObject.ResultType, optimizationInfo);
generator.Call(ReflectionHelpers.TypeUtilities_GetIterator);
generator.Call(ReflectionHelpers.TypeUtilities_Iterate);
// Call IEnumerable<object>.GetEnumerator()
generator.Call(ReflectionHelpers.IEnumerable_Object_GetEnumerator);
// Store the enumerator in a temporary variable.
var enumerator = generator.CreateTemporaryVariable(typeof(IEnumerator<object>));
generator.StoreVariable(enumerator);
var breakTarget = generator.CreateLabel();
var continueTarget = generator.DefineLabelPosition();
// Emit debugging information.
if (optimizationInfo.DebugDocument != null)
generator.MarkSequencePoint(optimizationInfo.DebugDocument, this.VariableSourceSpan);
// if (enumerator.MoveNext() == false)
// goto break-target;
generator.LoadVariable(enumerator);
generator.Call(ReflectionHelpers.IEnumerator_MoveNext);
generator.BranchIfFalse(breakTarget);
// lhs = enumerator.Current;
this.Variable.GenerateReference(generator, optimizationInfo);
generator.LoadVariable(enumerator);
generator.Call(ReflectionHelpers.IEnumerator_Object_Current);
this.Variable.GenerateSet(generator, optimizationInfo, PrimitiveType.Any, false);
// Emit the body statement(s).
optimizationInfo.PushBreakOrContinueInfo(this.Labels, breakTarget, continueTarget, labelledOnly: false);
this.Body.GenerateCode(generator, optimizationInfo);
optimizationInfo.PopBreakOrContinueInfo();
generator.Branch(continueTarget);
generator.DefineLabelPosition(breakTarget);
// Generate code for the end of the statement.
GenerateEndOfStatement(generator, optimizationInfo, statementLocals);
}
示例15: 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)
{
// Load the value to assign.
var compoundOperator = new BinaryExpression(GetCompoundBaseOperator(this.OperatorType), this.GetOperand(0), this.GetOperand(1));
compoundOperator.GenerateCode(generator, optimizationInfo);
// Duplicate the value so it remains on the stack afterwards.
//if (optimizationInfo.SuppressReturnValue == false)
generator.Duplicate();
// Store the value.
target.GenerateSet(generator, optimizationInfo, compoundOperator.ResultType, optimizationInfo.StrictMode);
}