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));
}
// ArrayConstructor.New(object[])
generator.Call(ReflectionHelpers.Array_New);
}
else if (this.Value is List<KeyValuePair<Expression, Expression>>)
{
// This is an object literal.
var properties = (List<KeyValuePair<Expression, Expression>>)this.Value;
// Create a new object.
EmitHelpers.LoadScriptEngine(generator);
generator.Call(ReflectionHelpers.ScriptEngine_Object);
generator.Call(ReflectionHelpers.Object_Construct);
foreach (var keyValuePair in properties)
{
Expression propertyName = keyValuePair.Key;
Expression propertyValue = keyValuePair.Value;
generator.Duplicate();
// The key can be a property name or an expression that evaluates to a name.
propertyName.GenerateCode(generator, optimizationInfo);
EmitConversion.ToPropertyKey(generator, propertyName.ResultType);
var functionValue = propertyValue as FunctionExpression;
if (functionValue != null && functionValue.DeclarationType == FunctionDeclarationType.Getter)
{
// Add a getter to the object.
functionValue.GenerateCode(generator, optimizationInfo);
// Support the inferred function displayName property.
if (propertyName is LiteralExpression && ((LiteralExpression)propertyName).Value is string)
functionValue.GenerateDisplayName(generator, optimizationInfo, "get " + (string)((LiteralExpression)propertyName).Value, true);
generator.Call(ReflectionHelpers.ReflectionHelpers_SetObjectLiteralGetter);
}
else if(functionValue != null && functionValue.DeclarationType == FunctionDeclarationType.Setter)
{
// Add a setter to the object.
functionValue.GenerateCode(generator, optimizationInfo);
// Support the inferred function displayName property.
if (propertyName is LiteralExpression && ((LiteralExpression)propertyName).Value is string)
functionValue.GenerateDisplayName(generator, optimizationInfo, "set " + (string)((LiteralExpression)propertyName).Value, true);
generator.Call(ReflectionHelpers.ReflectionHelpers_SetObjectLiteralSetter);
}
else
{
// Add a new property to the object.
propertyValue.GenerateCode(generator, optimizationInfo);
// Support the inferred function displayName property.
if (propertyValue is FunctionExpression && propertyName is LiteralExpression && ((LiteralExpression)propertyName).Value is string)
((FunctionExpression)propertyValue).GenerateDisplayName(generator, optimizationInfo, (string)((LiteralExpression)propertyName).Value, false);
EmitConversion.ToAny(generator, propertyValue.ResultType);
generator.Call(ReflectionHelpers.ReflectionHelpers_SetObjectLiteralValue);
}
}
}
else
throw new NotImplementedException("Unknown literal type.");
}