本文整理汇总了C#中Jurassic.Compiler.ILGenerator.CreateLabel方法的典型用法代码示例。如果您正苦于以下问题:C# ILGenerator.CreateLabel方法的具体用法?C# ILGenerator.CreateLabel怎么用?C# ILGenerator.CreateLabel使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Jurassic.Compiler.ILGenerator
的用法示例。
在下文中一共展示了ILGenerator.CreateLabel方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: 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();
GenerateStartOfStatement(generator, optimizationInfo, statementLocals);
// Generate code for the condition and coerce to a boolean.
this.Condition.GenerateCode(generator, optimizationInfo);
EmitConversion.ToBool(generator, this.Condition.ResultType);
// We will need a label at the end of the if statement.
var endOfEverything = generator.CreateLabel();
if (this.ElseClause == null)
{
// Jump to the end if the condition is false.
generator.BranchIfFalse(endOfEverything);
// Generate code for the if clause.
this.IfClause.GenerateCode(generator, optimizationInfo);
}
else
{
// Branch to the else clause if the condition is false.
var startOfElseClause = generator.CreateLabel();
generator.BranchIfFalse(startOfElseClause);
// Generate code for the if clause.
this.IfClause.GenerateCode(generator, optimizationInfo);
// Branch to the end of the if statement.
generator.Branch(endOfEverything);
// Generate code for the else clause.
generator.DefineLabelPosition(startOfElseClause);
this.ElseClause.GenerateCode(generator, optimizationInfo);
}
// Define the label at the end of the if statement.
generator.DefineLabelPosition(endOfEverything);
// Generate code for the end of the statement.
GenerateEndOfStatement(generator, optimizationInfo, statementLocals);
}
示例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();
GenerateStartOfStatement(generator, optimizationInfo, statementLocals);
// Emit the return value.
if (this.Value == null)
EmitHelpers.EmitUndefined(generator);
else
{
this.Value.GenerateCode(generator, optimizationInfo);
EmitConversion.ToAny(generator, this.Value.ResultType);
}
// Determine if this is the last statement in the function.
bool lastStatement = optimizationInfo.AbstractSyntaxTree is BlockStatement &&
((BlockStatement)optimizationInfo.AbstractSyntaxTree).Statements.Count > 0 &&
((BlockStatement)optimizationInfo.AbstractSyntaxTree).Statements[((BlockStatement)optimizationInfo.AbstractSyntaxTree).Statements.Count - 1] == this;
// The first return statement initializes the variable that holds the return value.
if (optimizationInfo.ReturnVariable == null)
optimizationInfo.ReturnVariable = generator.DeclareVariable(typeof(object), "returnValue");
// Store the return value in a variable.
generator.StoreVariable(optimizationInfo.ReturnVariable);
// There is no need to jump to the end of the function if this is the last statement.
if (lastStatement == false)
{
// The first return statement that needs to branch creates the return label. This is
// defined in FunctionmethodGenerator.GenerateCode() at the end of the function.
if (optimizationInfo.ReturnTarget == null)
optimizationInfo.ReturnTarget = generator.CreateLabel();
// Branch to the end of the function. Note: the return statement might be branching
// from inside a try { } or finally { } block to outside. EmitLongJump() handles this.
optimizationInfo.EmitLongJump(generator, optimizationInfo.ReturnTarget);
}
// 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)
{
// If a return value is not expected, generate only the side-effects.
/*if (optimizationInfo.SuppressReturnValue == true)
{
this.GenerateSideEffects(generator, optimizationInfo);
return;
}*/
// Emit the condition.
var condition = this.GetOperand(0);
condition.GenerateCode(generator, optimizationInfo);
// Convert the condition to a boolean.
EmitConversion.ToBool(generator, condition.ResultType);
// Branch if the condition is false.
var startOfElse = generator.CreateLabel();
generator.BranchIfFalse(startOfElse);
// Calculate the result type.
var outputType = this.ResultType;
// Emit the second operand and convert it to the result type.
var operand2 = this.GetOperand(1);
operand2.GenerateCode(generator, optimizationInfo);
EmitConversion.Convert(generator, operand2.ResultType, outputType, optimizationInfo);
// Branch to the end.
var end = generator.CreateLabel();
generator.Branch(end);
generator.DefineLabelPosition(startOfElse);
// Emit the third operand and convert it to the result type.
var operand3 = this.GetOperand(2);
operand3.GenerateCode(generator, optimizationInfo);
EmitConversion.Convert(generator, operand3.ResultType, outputType, optimizationInfo);
// Define the end label.
generator.DefineLabelPosition(end);
}
示例4: 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);
}
示例5: GenerateLogical
/// <summary>
/// Generates CIL for the logical operators.
/// </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 GenerateLogical(ILGenerator generator, OptimizationInfo optimizationInfo)
{
// Get the statically-determined types of the left and right operands.
PrimitiveType leftType = this.Left.ResultType;
PrimitiveType rightType = this.Right.ResultType;
// Load the left-hand side operand.
this.Left.GenerateCode(generator, optimizationInfo);
// Make sure the output type is consistant.
if (leftType != rightType)
{
if (PrimitiveTypeUtilities.IsNumeric(leftType) == true && PrimitiveTypeUtilities.IsNumeric(rightType) == true)
{
EmitConversion.ToNumber(generator, leftType);
leftType = PrimitiveType.Number;
}
else
{
EmitConversion.ToAny(generator, leftType);
leftType = PrimitiveType.Any;
}
}
// Duplicate and convert to a Boolean.
generator.Duplicate();
EmitConversion.ToBool(generator, leftType);
// Stack contains "left, (bool)left"
var endOfIf = generator.CreateLabel();
if (this.OperatorType == OperatorType.LogicalAnd)
generator.BranchIfFalse(endOfIf);
else
generator.BranchIfTrue(endOfIf);
// Stack contains "left". Load the right-hand side operand.
generator.Pop();
this.Right.GenerateCode(generator, optimizationInfo);
// Make sure the output type is consistant.
if (leftType != rightType)
{
if (PrimitiveTypeUtilities.IsNumeric(leftType) == true && PrimitiveTypeUtilities.IsNumeric(rightType) == true)
EmitConversion.ToNumber(generator, rightType);
else
EmitConversion.ToAny(generator, rightType);
}
// Define the label used above.
generator.DefineLabelPosition(endOfIf);
}
示例6: GenerateSet
//.........这里部分代码省略.........
// Call the indexer.
generator.LoadVariable(value);
generator.LoadBoolean(optimizationInfo.StrictMode);
generator.Call(ReflectionHelpers.ObjectInstance_SetPropertyValue_Int);
}
else if (propertyName != null)
{
//// Load the left-hand side and convert to an object instance.
//var lhs = this.GetOperand(0);
//lhs.GenerateCode(generator, optimizationInfo);
//EmitConversion.ToObject(generator, lhs.ResultType);
//// Call the indexer.
//generator.LoadString(propertyName);
//generator.LoadVariable(value);
//generator.LoadBoolean(optimizationInfo.StrictMode);
//generator.Call(ReflectionHelpers.ObjectInstance_SetPropertyValue_String);
// Named property modification (e.g. x.property = y)
// -------------------------------------------------
// __object_cacheKey = null;
// __object_property_cachedIndex = 0;
// ...
// if (__object_cacheKey != object.InlineCacheKey)
// object.InlineSetPropertyValue("property", value, strictMode, out __object_property_cachedIndex, out __object_cacheKey)
// else
// object.InlinePropertyValues[__object_property_cachedIndex] = value;
// Load the left-hand side and convert to an object instance.
var lhs = this.GetOperand(0);
lhs.GenerateCode(generator, optimizationInfo);
EmitConversion.ToObject(generator, lhs.ResultType);
// TODO: share these variables somehow.
var cacheKey = generator.DeclareVariable(typeof(object));
var cachedIndex = generator.DeclareVariable(typeof(int));
// Store the object into a temp variable.
var objectInstance = generator.DeclareVariable(PrimitiveType.Object);
generator.StoreVariable(objectInstance);
// if (__object_cacheKey != object.InlineCacheKey)
generator.LoadVariable(cacheKey);
generator.LoadVariable(objectInstance);
generator.Call(ReflectionHelpers.ObjectInstance_InlineCacheKey);
var elseClause = generator.CreateLabel();
generator.BranchIfEqual(elseClause);
// xxx = object.InlineSetPropertyValue("property", value, strictMode, out __object_property_cachedIndex, out __object_cacheKey)
generator.LoadVariable(objectInstance);
generator.LoadString(propertyName);
generator.LoadVariable(value);
generator.LoadBoolean(optimizationInfo.StrictMode);
generator.LoadAddressOfVariable(cachedIndex);
generator.LoadAddressOfVariable(cacheKey);
generator.Call(ReflectionHelpers.ObjectInstance_InlineSetPropertyValue);
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));
// End of the if statement
generator.DefineLabelPosition(endOfIf);
}
else
{
// Dynamic property access
// -----------------------
// xxx = object.Get(x)
// Load the left-hand side and convert to an object instance.
var lhs = this.GetOperand(0);
lhs.GenerateCode(generator, optimizationInfo);
EmitConversion.ToObject(generator, lhs.ResultType);
// Load the property name and convert to a string.
var rhs = this.GetOperand(1);
rhs.GenerateCode(generator, optimizationInfo);
EmitConversion.ToString(generator, rhs.ResultType);
// Call the indexer.
generator.LoadVariable(value);
generator.LoadBoolean(optimizationInfo.StrictMode);
generator.Call(ReflectionHelpers.ObjectInstance_SetPropertyValue_String);
}
// The temporary variable is no longer needed.
generator.ReleaseTemporaryVariable(value);
}
示例7: GenerateGet
/// <summary>
/// Pushes the value of the reference onto 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="throwIfUnresolvable"> <c>true</c> to throw a ReferenceError exception if
/// the name is unresolvable; <c>false</c> to output <c>null</c> instead. </param>
public void GenerateGet(ILGenerator generator, OptimizationInfo optimizationInfo, bool throwIfUnresolvable)
{
string propertyName = null;
TypeOfMemberAccess memberAccessType = DetermineTypeOfMemberAccess(optimizationInfo, out propertyName);
if (memberAccessType == TypeOfMemberAccess.ArrayIndex)
{
// Array indexer
// -------------
// xxx = object[index]
// Call the indexer.
generator.Call(ReflectionHelpers.ObjectInstance_GetPropertyValue_Int);
}
else if (memberAccessType == TypeOfMemberAccess.Static)
{
// Named property access (e.g. x = y.property)
// -------------------------------------------
// __object_cacheKey = null;
// __object_property_cachedIndex = 0;
// ...
// if (__object_cacheKey != object.InlineCacheKey)
// xxx = object.InlineGetPropertyValue("property", out __object_property_cachedIndex, out __object_cacheKey)
// else
// xxx = object.InlinePropertyValues[__object_property_cachedIndex];
// TODO: share these variables somehow.
var cacheKey = generator.DeclareVariable(typeof(object));
var cachedIndex = generator.DeclareVariable(typeof(int));
// Store the object into a temp variable.
var objectInstance = generator.DeclareVariable(PrimitiveType.Object);
generator.StoreVariable(objectInstance);
// if (__object_cacheKey != object.InlineCacheKey)
generator.LoadVariable(cacheKey);
generator.LoadVariable(objectInstance);
generator.Call(ReflectionHelpers.ObjectInstance_InlineCacheKey);
var elseClause = generator.CreateLabel();
generator.BranchIfEqual(elseClause);
// value = object.InlineGetProperty("property", out __object_property_cachedIndex, out __object_cacheKey)
generator.LoadVariable(objectInstance);
generator.LoadString(propertyName);
generator.LoadAddressOfVariable(cachedIndex);
generator.LoadAddressOfVariable(cacheKey);
generator.Call(ReflectionHelpers.ObjectInstance_InlineGetPropertyValue);
var endOfIf = generator.CreateLabel();
generator.Branch(endOfIf);
// else
generator.DefineLabelPosition(elseClause);
// value = object.InlinePropertyValues[__object_property_cachedIndex];
generator.LoadVariable(objectInstance);
generator.Call(ReflectionHelpers.ObjectInstance_InlinePropertyValues);
generator.LoadVariable(cachedIndex);
generator.LoadArrayElement(typeof(object));
// End of the if statement
generator.DefineLabelPosition(endOfIf);
}
else
{
// Dynamic property access
// -----------------------
// xxx = object.Get(x)
// Call Get(object)
generator.Call(ReflectionHelpers.ObjectInstance_GetPropertyValue_Object);
}
}
示例8: GenerateCode
/// <summary>
/// Generates IL for the script.
/// </summary>
/// <param name="generator"> The generator to output the CIL to. </param>
/// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
protected override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
{
// Method signature: object FunctionDelegate(Compiler.Scope scope, object thisObject, Library.FunctionInstance functionObject, object[] arguments)
// Initialize the scope (note: the initial scope for a function is always declarative).
this.InitialScope.GenerateScopeCreation(generator, optimizationInfo);
// Verify the scope is correct.
VerifyScope(generator);
// In ES3 the "this" value must be an object. See 10.4.3 in the spec.
if (this.StrictMode == false && this.MethodOptimizationHints.HasThis == true)
{
// if (thisObject == null || thisObject == Null.Value || thisObject == Undefined.Value)
EmitHelpers.LoadThis(generator);
generator.LoadNull();
generator.CompareEqual();
EmitHelpers.LoadThis(generator);
EmitHelpers.EmitNull(generator);
generator.CompareEqual();
generator.BitwiseOr();
EmitHelpers.LoadThis(generator);
EmitHelpers.EmitUndefined(generator);
generator.CompareEqual();
generator.BitwiseOr();
// {
var startOfFalse = generator.CreateLabel();
generator.BranchIfFalse(startOfFalse);
// thisObject = engine.Global;
EmitHelpers.LoadScriptEngine(generator);
generator.Call(ReflectionHelpers.ScriptEngine_Global);
// } else {
var endOfIf = generator.CreateLabel();
generator.Branch(endOfIf);
generator.DefineLabelPosition(startOfFalse);
// thisObject = TypeConverter.ToObject(thisObject);
EmitHelpers.LoadThis(generator);
EmitConversion.ToObject(generator, PrimitiveType.Any);
// }
generator.DefineLabelPosition(endOfIf);
EmitHelpers.StoreThis(generator);
}
// Transfer the function name into the scope.
if (string.IsNullOrEmpty(this.Name) == false &&
this.ArgumentNames.Contains(this.Name) == false &&
optimizationInfo.MethodOptimizationHints.HasVariable(this.Name))
{
EmitHelpers.LoadFunction(generator);
var functionName = new NameExpression(this.InitialScope, this.Name);
functionName.GenerateSet(generator, optimizationInfo, PrimitiveType.Any, false);
}
// Transfer the arguments object into the scope.
if (this.MethodOptimizationHints.HasArguments == true && this.ArgumentNames.Contains("arguments") == false)
{
// prototype
EmitHelpers.LoadScriptEngine(generator);
generator.Call(ReflectionHelpers.ScriptEngine_Object);
generator.Call(ReflectionHelpers.FunctionInstance_InstancePrototype);
// callee
EmitHelpers.LoadFunction(generator);
generator.CastClass(typeof(Library.UserDefinedFunction));
// scope
EmitHelpers.LoadScope(generator);
generator.CastClass(typeof(DeclarativeScope));
// argumentValues
EmitHelpers.LoadArgumentsArray(generator);
generator.NewObject(ReflectionHelpers.Arguments_Constructor);
var arguments = new NameExpression(this.InitialScope, "arguments");
arguments.GenerateSet(generator, optimizationInfo, PrimitiveType.Any, false);
}
// Transfer the argument values into the scope.
// Note: the arguments array can be smaller than expected.
if (this.ArgumentNames.Count > 0)
{
var endOfArguments = generator.CreateLabel();
for (int i = 0; i < this.ArgumentNames.Count; i++)
{
// Check if a duplicate argument name exists.
bool duplicate = false;
for (int j = i + 1; j < this.ArgumentNames.Count; j++)
if (this.ArgumentNames[i] == this.ArgumentNames[j])
{
duplicate = true;
break;
}
if (duplicate == true)
continue;
//.........这里部分代码省略.........
示例9: GenerateCode
/// <summary>
/// Generates IL for the script.
/// </summary>
/// <param name="generator"> The generator to output the CIL to. </param>
/// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
protected override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
{
// Declare a variable to store the eval result.
optimizationInfo.EvalResult = generator.DeclareVariable(typeof(object));
if (this.StrictMode == true)
{
// Create a new scope.
this.InitialScope.GenerateScopeCreation(generator, optimizationInfo);
}
// Verify the scope is correct.
VerifyScope(generator);
// Initialize any declarations.
this.InitialScope.GenerateDeclarations(generator, optimizationInfo);
// Generate the main body of code.
this.AbstractSyntaxTree.GenerateCode(generator, optimizationInfo);
// Make the return value from the method the eval result.
generator.LoadVariable(optimizationInfo.EvalResult);
// If the result is null, convert it to undefined.
var end = generator.CreateLabel();
generator.Duplicate();
generator.BranchIfNotNull(end);
generator.Pop();
EmitHelpers.EmitUndefined(generator);
generator.DefineLabelPosition(end);
}
示例10: 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);
}
示例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)
{
// Literals cannot have side-effects so if a return value is not expected then generate
// nothing.
//if (optimizationInfo.SuppressReturnValue == true)
// return;
if (this.Value is int)
generator.LoadInt32((int)this.Value);
else if (this.Value is double)
generator.LoadDouble((double)this.Value);
else if (this.Value is string)
generator.LoadString((string)this.Value);
else if (this.Value is bool)
generator.LoadBoolean((bool)this.Value);
else if (this.Value is RegularExpressionLiteral)
{
// RegExp
var sharedRegExpVariable = optimizationInfo.GetRegExpVariable(generator, (RegularExpressionLiteral)this.Value);
var label1 = generator.CreateLabel();
var label2 = generator.CreateLabel();
// if (sharedRegExp == null) {
generator.LoadVariable(sharedRegExpVariable);
generator.LoadNull();
generator.BranchIfNotEqual(label1);
// sharedRegExp = Global.RegExp.Construct(source, flags)
EmitHelpers.LoadScriptEngine(generator);
generator.Call(ReflectionHelpers.ScriptEngine_RegExp);
generator.LoadString(((RegularExpressionLiteral)this.Value).Pattern);
generator.LoadString(((RegularExpressionLiteral)this.Value).Flags);
generator.Call(ReflectionHelpers.RegExp_Construct);
generator.Duplicate();
generator.StoreVariable(sharedRegExpVariable);
// } else {
generator.Branch(label2);
generator.DefineLabelPosition(label1);
// Global.RegExp.Construct(sharedRegExp, flags)
EmitHelpers.LoadScriptEngine(generator);
generator.Call(ReflectionHelpers.ScriptEngine_RegExp);
generator.LoadVariable(sharedRegExpVariable);
generator.LoadNull();
generator.Call(ReflectionHelpers.RegExp_Construct);
// }
generator.DefineLabelPosition(label2);
}
else if (this.Value == Null.Value)
{
// Null.
EmitHelpers.EmitNull(generator);
}
else if (this.Value == Undefined.Value)
{
// Undefined.
EmitHelpers.EmitUndefined(generator);
}
else if (this.Value is List<Expression>)
{
// Construct an array literal.
var arrayLiteral = (List<Expression>)this.Value;
// Operands for ArrayConstructor.New() are: an ArrayConstructor instance (ArrayConstructor), an array (object[])
// ArrayConstructor
EmitHelpers.LoadScriptEngine(generator);
generator.Call(ReflectionHelpers.ScriptEngine_Array);
// object[]
generator.LoadInt32(arrayLiteral.Count);
generator.NewArray(typeof(object));
for (int i = 0; i < arrayLiteral.Count; i ++)
{
// Operands for StoreArrayElement() are: an array (object[]), index (int), value (object).
// Array
generator.Duplicate();
// Index
generator.LoadInt32(i);
// Value
var elementExpression = arrayLiteral[i];
if (elementExpression == null)
generator.LoadNull();
else
{
elementExpression.GenerateCode(generator, optimizationInfo);
EmitConversion.ToAny(generator, elementExpression.ResultType);
}
// Store the element value.
generator.StoreArrayElement(typeof(object));
}
//.........这里部分代码省略.........
示例12: ToString
/// <summary>
/// Pops the value on the stack, converts it to a string, then pushes the result onto the
/// stack.
/// </summary>
/// <param name="generator"> The IL generator. </param>
/// <param name="fromType"> The type to convert from. </param>
public static void ToString(ILGenerator generator, PrimitiveType fromType)
{
// Check that a conversion is actually necessary.
if (fromType == PrimitiveType.String)
return;
switch (fromType)
{
case PrimitiveType.Undefined:
// Converting from undefined produces "undefined".
generator.Pop();
generator.LoadString("undefined");
break;
case PrimitiveType.Null:
// Converting from null produces "null".
generator.Pop();
generator.LoadString("null");
break;
case PrimitiveType.Bool:
// Converting from a boolean produces "false" if the boolean is false, or "true" if the boolean is true.
var elseClause = generator.CreateLabel();
var endOfIf = generator.CreateLabel();
generator.BranchIfFalse(elseClause);
generator.LoadString("true");
generator.Branch(endOfIf);
generator.DefineLabelPosition(elseClause);
generator.LoadString("false");
generator.DefineLabelPosition(endOfIf);
break;
case PrimitiveType.ConcatenatedString:
generator.Call(ReflectionHelpers.ConcatenatedString_ToString);
break;
case PrimitiveType.Int32:
case PrimitiveType.UInt32:
case PrimitiveType.Number:
case PrimitiveType.Any:
case PrimitiveType.Object:
// Otherwise, fall back to calling TypeConverter.ToString()
if (PrimitiveTypeUtilities.IsValueType(fromType))
generator.Box(fromType);
generator.Call(ReflectionHelpers.TypeConverter_ToString);
break;
default:
throw new NotImplementedException(string.Format("Unsupported primitive type: {0}", fromType));
}
}
示例13: 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);
}
示例14: 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();
}
示例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;
//.........这里部分代码省略.........