예제 #1
0
        /// <summary>
        /// Creates a new GlobalMethodGenerator instance.
        /// </summary>
        /// <param name="engine"> The script engine. </param>
        /// <param name="source"> The source of javascript code. </param>
        /// <param name="options"> Options that influence the compiler. </param>
        public GlobalMethodGenerator(ScriptEngine engine, ScriptSource source, CompilerOptions options)
            : base(engine, new ObjectScope(engine, engine.GlobalPrototype), source, options)
        {
            // Apply global scope:
            Engine.GlobalScope = InitialScope as ObjectScope;

            // Set the global 'this':
            Library.PropertyVariable pv = Engine.SetGlobalType("this", Engine.GlobalPrototype.Type, Library.PropertyAttributes.Sealed);

            // When loaded, we set 'this' to being our Global object:
            Engine.AwaitStart(new AwaitingStart(pv, null, true));
        }
예제 #2
0
        internal override void ResolveVariables(OptimizationInfo optimizationInfo)
        {
            // Resolve kids too:
            base.ResolveVariables(optimizationInfo);

            // Is it an object literal?
            var properties = this.Value as List <KeyValuePair <Expression, Expression> >;

            if (properties == null)
            {
                // Not an object literal! How about an array?

                // Get the expressions:
                List <Expression> exprs = this.Value as List <Expression>;

                if (exprs == null)
                {
                    // Not an array either! Quit there.
                    return;
                }

                // For each one..
                foreach (Expression expr in exprs)
                {
                    // Resolve it:
                    expr.ResolveVariables(optimizationInfo);
                }

                return;
            }

            if (CreatedPrototype != null)
            {
                // Already made it!
                return;
            }

            // We'll generate a prototype and a custom object type for it:
            CreatedPrototype = optimizationInfo.Engine.Prototypes.Create();

            // We'll generate a prototype and a custom object type for it:
            Library.Prototype proto = CreatedPrototype;

            foreach (var keyValuePair in properties)
            {
                string     propertyName  = keyValuePair.Key.ToString();
                Expression propertyValue = keyValuePair.Value;

                if (propertyValue is Expression)
                {
                    // Add a new property to the object.

                    var dataPropertyValue = (Expression)propertyValue;

                    // Resolve it:
                    dataPropertyValue.ResolveVariables(optimizationInfo);

                    Type valueType = dataPropertyValue.GetResultType(optimizationInfo);

                    // Create the property now:
                    Library.PropertyVariable pv = proto.AddProperty(propertyName, Library.PropertyAttributes.FullAccess, valueType);

                    // If it's a function value then it might be constant.
                    // It might be a constant string/ number too, so track them as well.
                    pv.TryLoadConstant(dataPropertyValue);
                }
                else
                {
                    throw new InvalidOperationException("Invalid property value type in object literal.");
                }
            }
        }
예제 #3
0
        /// <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.RootExpression == this)
            {
                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.OnConstruct(source, flags)
                EmitHelpers.LoadPrototypes(generator);
                generator.LoadField(ReflectionHelpers.PrototypeLookup_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.OnConstruct(sharedRegExp, flags)
                EmitHelpers.LoadPrototypes(generator);
                generator.LoadField(ReflectionHelpers.PrototypeLookup_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.LoadEngine(generator);

                // 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.GetResultType(optimizationInfo));
                    }

                    // 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;

                // We'll generate a prototype and a custom object type for it:
                Library.Prototype proto = CreatedPrototype;

                // Create a new object.
                generator.NewObject(proto.TypeConstructor);

                foreach (var keyValuePair in properties)
                {
                    string     propertyName  = keyValuePair.Key.ToString();
                    Expression propertyValue = keyValuePair.Value;

                    // Duplicate the object ref:
                    generator.Duplicate();

                    // Add a new property to the object.

                    Type valueType = propertyValue.GetResultType(optimizationInfo);

                    // Get the property:
                    Library.PropertyVariable pv = proto.GetProperty(propertyName);

                    // Set it:
                    pv.Set(generator, optimizationInfo, false, valueType, delegate(bool two){
                        if (pv.IsConstant)
                        {
                            // Emit the constant:
                            EmitHelpers.EmitValue(generator, pv.ConstantValue);
                        }
                        else
                        {
                            // Write the value to set now:
                            propertyValue.GenerateCode(generator, optimizationInfo);
                        }

                        // Note: This one always ignores 'two'
                    });
                }
            }
            else
            {
                throw new NotImplementedException("Unknown literal type.");
            }
        }