示例#1
0
        /// <summary>
        /// Generates CIL for the typeof 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>
        private void GenerateTypeof(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            if (this.Operand is NameExpression)
            {
                // Unresolvable references must return "undefined" rather than throw an error.
                ((NameExpression)this.Operand).GenerateGet(generator, optimizationInfo, false);
            }
            else
            {
                // Emit code for resolving the value of the operand.
                this.Operand.GenerateCode(generator, optimizationInfo);
            }

            if (optimizationInfo.RootExpression == this)
            {
                // Pop it and quit.
                generator.Pop();
                return;
            }

            // Convert to System.Object.
            EmitConversion.ToAny(generator, this.Operand.GetResultType(optimizationInfo));

            // Call TypeUtilities.TypeOf(operand).
            generator.Call(ReflectionHelpers.TypeUtilities_TypeOf);
        }
        /// <summary>
        /// Gets the type that results from evaluating this expression.
        /// </summary>
        public override Type GetResultType(OptimizationInfo optimizationInfo)
        {
            // The result is either the type of the second operand or the third operand.
            var a = this.GetOperand(1).GetResultType(optimizationInfo);
            var b = this.GetOperand(2).GetResultType(optimizationInfo);

            if (a == b)
            {
                return(a);
            }
            if (PrimitiveTypeUtilities.IsNumeric(a) == true && PrimitiveTypeUtilities.IsNumeric(b) == true)
            {
                return(typeof(double));
            }

            if (StaticResult != null)
            {
                // Convert it to a bool:
                bool result = TypeConverter.ToBoolean(StaticResult);

                if (result)
                {
                    return(a);
                }

                return(b);
            }

            // Don't know if it'll be a or b, and they're distinctive types.
            return(typeof(object));
        }
示例#3
0
        /// <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)
        {
            if (optimizationInfo.RootExpression == this)
            {
                // Return isn't in use. Do nothing.
                Left.GenerateCode(generator, optimizationInfo);
                Right.GenerateCode(generator, optimizationInfo);
                generator.Pop();
                generator.Pop();
                return;
            }

            // Dynamic resolve required (The 'Evaluate' method above diverts away otherwise).

            // Engine required:
            EmitHelpers.LoadEngine(generator);

            // Emit the object:
            Right.GenerateCode(generator, optimizationInfo);

            // Emit the left-hand side expression and convert it to a string.
            Left.GenerateCode(generator, optimizationInfo);
            EmitConversion.ToString(generator, Left.GetResultType(optimizationInfo));

            // Property name is now on the stack too.

            // Emit the property test:
            generator.Call(ReflectionHelpers.Object_HasProperty);
        }
示例#4
0
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Get the previous root - we'll be changing it:
            Expression prevRoot = optimizationInfo.RootExpression;

            // Labelled is now the root:
            Labelled.SetRoot(optimizationInfo);

            if (Labelled.DefaultBreakStatementBehaviour)
            {
                // Set up the information needed by the break statement.
                ILLabel endOfStatement = generator.CreateLabel();
                optimizationInfo.PushBreakOrContinueInfo(labels, endOfStatement, null, true);

                Labelled.GenerateCode(generator, optimizationInfo);

                // Revert the information needed by the break statement.
                generator.DefineLabelPosition(endOfStatement);
                optimizationInfo.PopBreakOrContinueInfo();
            }
            else
            {
                // Loop, For-In, For-Of or Switch only.
                optimizationInfo.Labels = labels;
                Labelled.GenerateCode(generator, optimizationInfo);
            }

            // Restore root:
            optimizationInfo.RootExpression = prevRoot;
        }
示例#5
0
        /// <summary>
        /// Stores the value on the top of the stack in the 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>
        /// <param name="valueType"> The primitive type of the value that is on the top of the stack. </param>
        /// <param name="throwIfUnresolvable"> <c>true</c> to throw a ReferenceError exception if
        /// the name is unresolvable; <c>false</c> to create a new property instead. </param>
        public void GenerateSet(ILGenerator generator, OptimizationInfo optimizationInfo, bool rIU, Type valueType, SetValueMethod value, bool throwIfUnresolvable)
        {
            if (Variable == null)
            {
                // Create a new variable:
                Variable = Scope.AddVariable(Name, valueType, null);
            }
            else if (Variable.IsHoisted(Scope))
            {
                Wrench.Log.Add("Attempted to set a hoisted variable. This is slow and is usually unnecessary. Ignoring it by treating it as a local.");

                // This happens in this situation:
                // function a(){
                //  var b="hello!";
                //  var test=function(){
                //     b="overwriting a hoisted variable here (Nitrassic treats it as a new local in test's scope)";
                //   };
                //  // Nitrassic is wrong if this happens:
                //  test();
                //  console.log(b); // *should* be the value set from inside test
                // }

                // Create a new variable:
                Variable = Scope.AddVariable(Name, valueType, null);
            }

            // Output a set now:
            Variable.Set(generator, optimizationInfo, rIU, valueType, value);
        }
示例#6
0
        /// <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)
        {
            // Load the value to assign.
            var rhs = GetOperand(1);

            // Potentially transferring a constant here.
            // Note that all of the others affect the source value in some way
            // so this is the only one which can potentially transfer a constant like this.
            object constValue = target.GetConstantValue();

            // Store the value.
            target.GenerateSet(generator, optimizationInfo, optimizationInfo.RootExpression != this, rhs.GetResultType(optimizationInfo), delegate(bool two)
            {
                // Generate the code:

                if (constValue != null)
                {
                    // Straight emit the constant value (Note that it could be a function - it handles that for us):
                    EmitHelpers.EmitValue(generator, constValue);
                }
                else
                {
                    rhs.GenerateCode(generator, optimizationInfo);
                }

                if (two)
                {
                    // Duplicate the value so it remains on the stack afterwards.
                    generator.Duplicate();
                }
            }, optimizationInfo.StrictMode);
        }
示例#7
0
 /// <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)
 {
     // Emit an unconditional branch.
     // Note: the continue statement might be branching from inside a try { } or finally { }
     // block to outside.  EmitLongJump() handles this.
     optimizationInfo.EmitLongJump(generator, optimizationInfo.GetContinueTarget(this.Label));
 }
示例#8
0
        /// <summary>
        /// Gets the type that results from evaluating this expression.
        /// </summary>
        public override Type GetResultType(OptimizationInfo optimizationInfo)
        {
            switch (this.OperatorType)
            {
            case OperatorType.Plus:
            case OperatorType.Minus:
                return(typeof(double));

            case OperatorType.BitwiseNot:
                return(typeof(int));

            case OperatorType.LogicalNot:
                return(typeof(bool));

            case OperatorType.Void:
                return(typeof(Nitrassic.Undefined));

            case OperatorType.Typeof:
                return(typeof(string));

            case OperatorType.Delete:
                return(typeof(bool));

            default:
                throw new NotImplementedException(string.Format("Unsupported operator {0}", this.OperatorType));
            }
        }
示例#9
0
        /// <summary>
        /// Gets the type that results from evaluating this expression.
        /// </summary>
        public override Type GetResultType(OptimizationInfo optimizationInfo)
        {
            // Get the operand:
            var operand = this.GetRawOperand(0);

            // Get as a call expr:
            FunctionCallExpression function = operand as FunctionCallExpression;

            if (function != null)
            {
                // Set IsConstructCall so a potential resolve runs correctly:
                optimizationInfo.IsConstructCall = true;
            }

            Type fType = operand.GetResultType(optimizationInfo);

            if (function != null)
            {
                // Clear ICC:
                optimizationInfo.IsConstructCall = false;
            }

            if (function.IsUserDefined)
            {
                // It's user defined which means the return type is actually the instance type:
                fType = function.InstanceType(optimizationInfo.Engine);
            }

            return(fType);
        }
示例#10
0
        internal override void ResolveVariables(OptimizationInfo optimizationInfo)
        {
            // Apply var:
            Variable.ApplyType(optimizationInfo, typeof(string));

            base.ResolveVariables(optimizationInfo);
        }
示例#11
0
        internal override void Set(ILGenerator generator, OptimizationInfo optimizationInfo, bool rIU, Type valueType, SetValueMethod value)
        {
            if (_Type == null)
            {
                _Type = valueType;
            }
            else if (_Type != valueType)
            {
                // Essentially declaring a new variable.
                _Type = valueType;
                Store = null;
            }

            // Declare an IL local variable if no storage location has been allocated yet.
            if (Store == null)
            {
                Store = generator.DeclareVariable(valueType, Name);
            }

            // Load the value:
            value(rIU);

            // Store the value in the variable.
            generator.StoreVariable(Store);
        }
示例#12
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)
        {
            // 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);
                Values[i].GenerateCode(generator, optimizationInfo);
                EmitConversion.ToString(generator, Values[i].GetResultType(optimizationInfo));
                generator.StoreArrayElement(typeof(string));
            }

            // Call String.Concat(string[])
            generator.CallStatic(ReflectionHelpers.String_Concat);
        }
示例#13
0
        /// <summary>Resolves the type of variable this is referencing.</summary>
        internal override void ResolveVariables(OptimizationInfo optimizationInfo)
        {
            if (_Variable != null)
            {
                return;
            }

            // Resolve kids:
            base.ResolveVariables(optimizationInfo);

            var scope = this.Scope;

            while (scope != null)
            {
                // Is the variable in this scope?
                _Variable = scope.GetVariable(Name);

                if (_Variable != null)
                {
                    // The scope has been optimized away.  The value of the variable is stored
                    // in an ILVariable.

                    // The variable was found - no need to search any more parent scopes.
                    return;
                }

                scope = scope.ParentScope;
            }
        }
示例#14
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)
        {
            // The left hand side needs to be a variable reference or member access.
            var target = this.GetOperand(0) as IReferenceExpression;

            switch (this.OperatorType)
            {
            case OperatorType.Assignment:
                // Standard assignment operator.
                GenerateAssignment(generator, optimizationInfo, target);
                break;

            case OperatorType.PostIncrement:
                GenerateIncrementOrDecrement(generator, optimizationInfo, target, true, true);
                break;

            case OperatorType.PostDecrement:
                GenerateIncrementOrDecrement(generator, optimizationInfo, target, true, false);
                break;

            case OperatorType.PreIncrement:
                GenerateIncrementOrDecrement(generator, optimizationInfo, target, false, true);
                break;

            case OperatorType.PreDecrement:
                GenerateIncrementOrDecrement(generator, optimizationInfo, target, false, false);
                break;

            default:
                // All other compound operators.
                GenerateCompoundAssignment(generator, optimizationInfo, target);
                break;
            }
        }
示例#15
0
        /// <summary>
        /// Gets the type that results from evaluating this expression.
        /// </summary>
        public override Type GetResultType(OptimizationInfo optimizationInfo)
        {
            var type = this.OperatorType;

            if (type == OperatorType.PostIncrement ||
                type == OperatorType.PostDecrement ||
                type == OperatorType.PreIncrement ||
                type == OperatorType.PreDecrement)
            {
                // If the input var is an int, the out is an int too:
                Type input = GetOperand(0).GetResultType(optimizationInfo);

                if (input == typeof(int) || input == typeof(uint) || input == typeof(short) || input == typeof(ushort))
                {
                    return(input);
                }
                else if (input == typeof(double))
                {
                    return(typeof(double));
                }
                else
                {
                    throw new Exception("Unable to increment/ decrement that (not a suitable type). " + input);
                }
            }

            if (type == OperatorType.Assignment)
            {
                return(this.GetOperand(1).GetResultType(optimizationInfo));
            }

            var compoundOperator = new BinaryExpression(GetCompoundBaseOperator(type), this.GetOperand(0), this.GetOperand(1));

            return(compoundOperator.GetResultType(optimizationInfo));
        }
        /// <summary>Gets the compiled function for the given args set. Note that this args set
        /// is the actual types and always includes the 'this' keywords type.</summary>
        public Library.UserDefinedFunction GetCompiled(Type[] args, ScriptEngine engine, bool isConstructor)
        {
            int genCount = GeneratedMethods.Count;

            for (int i = 0; i < genCount; i++)
            {
                if (GeneratedMethods[i].ArgsEqual(args))
                {
                    // Got a match! Already compiled it.
                    return(GeneratedMethods[i]);
                }
            }

            // Need to compile it now with our given arg types.
            int argCount = args == null?0:args.Length;

            // The source contains a fixed number of args; it goes up to this:
            int maxArg = Arguments.Count;

            // First, map args to a block of ArgVariable objects:
            ArgVariable[] argsSet = new ArgVariable[argCount];

            for (int i = 0; i < argCount; i++)
            {
                // Setup the arg variable:
                ArgVariable curArg;

                if (i < maxArg)
                {
                    // Use the existing args object so it correctly updates in the scope:
                    curArg = Arguments[i];
                }
                else
                {
                    // Need to create a fake one:
                    curArg = new ArgVariable("@unused-arg-" + i);
                }

                // Apply type (a little different here as we have to account for null too):
                curArg.RawType = args[i];

                // Apply to set:
                argsSet[i] = curArg;
            }

            // If we're passing less args than the source supports, update the types of those unused args to being 'Undefined':
            for (int i = argCount; i < maxArg; i++)
            {
                Arguments[i].Type = typeof(Nitrassic.Undefined);
            }

            // Create info:
            OptimizationInfo info = new OptimizationInfo(engine);

            info.IsConstructor = isConstructor;

            // Generate it!
            return(GenerateCode(argsSet, info));
        }
示例#17
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)
        {
            // Setup the method info.
            // this.context.SetupMethod(optimizationInfo);

            // Add the generated method to the nested function list.
            if (optimizationInfo.NestedFunctions == null)
            {
                optimizationInfo.NestedFunctions = new List <FunctionMethodGenerator>();
            }
            optimizationInfo.NestedFunctions.Add(context);

            // Add all the nested methods to the parent list.
            // Note: it's used to compute which variables are being hoisted.
            if (this.context.Dependencies != null)
            {
                foreach (var nestedFunctionExpression in this.context.Dependencies)
                {
                    optimizationInfo.NestedFunctions.Add(nestedFunctionExpression);
                }
            }

            if (HoistValues != null)
            {
                // Script engine:
                EmitHelpers.LoadEngine(generator);

                // Method ID:
                generator.LoadInt64(context.MethodID);

                generator.LoadInt32(HoistValues.Count);

                // Hoist vars array:
                generator.NewArray(typeof(object));

                // Load each one:
                for (int i = 0; i < HoistValues.Count; i++)
                {
                    generator.Duplicate();
                    generator.LoadInt32(i);

                    // Load the variable value:
                    Type type = HoistValues[i].Get(generator);

                    // Box if necessary:
                    EmitConversion.ToAny(generator, type);

                    generator.StoreArrayElement(typeof(object));
                }

                generator.NewObject(ReflectionHelpers.HoistFunctionReference_Constructor);
            }
            else
            {
                // body
                generator.LoadInt64(context.MethodID);
                generator.Call(ReflectionHelpers.MethodLookup_Load);
            }
        }
示例#18
0
 /// <summary>
 /// Resolves variables and property references.
 /// </summary>
 internal virtual void ResolveVariables(OptimizationInfo optimizationInfo)
 {
     // Resolve all child nodes:
     foreach (AstNode child in ChildNodes)
     {
         // Resolve now:
         child.ResolveVariables(optimizationInfo);
     }
 }
示例#19
0
        public void TryApplyConstant(OptimizationInfo optimizationInfo, bool isConst)
        {
            Variable v = Variable;

            if (v != null)
            {
                v.IsConstant = isConst;
            }
        }
示例#20
0
        /// <summary>
        /// Gets the type that results from evaluating this expression.
        /// </summary>
        public override Type GetResultType(OptimizationInfo optimizationInfo)
        {
            if (HoistValues != null)
            {
                return(typeof(HoistFunctionReference));
            }

            return(typeof(FunctionMethodGenerator));
        }
示例#21
0
        private FunctionCallExpression AttemptConversion(OptimizationInfo optimizationInfo)
        {
            var operand = this.GetRawOperand(0);

            // Try a NameExpression which refs a constructor instead.
            NameExpression nameExpr = operand as NameExpression;

            if (nameExpr == null)
            {
                return(null);
            }

            // Get the type:
            Type type = nameExpr.Variable.Type;

            // Get the prototype;
            Library.Prototype proto = optimizationInfo.Engine.Prototypes.Get(type);

            // Get ctr object, which may be a set:
            object onCtr = proto.OnConstruct;

            if (onCtr == null)
            {
                throw new Exception("Didn't recognise that as a suitable constructable object");
            }

            // Ok! It could be a set - let's check:
            MethodGroup group = onCtr as MethodGroup;

            System.Reflection.MethodBase resolvedMethod = null;

            if (group == null)
            {
                // It must be MethodBase - it can't be anything else:
                resolvedMethod = onCtr as System.Reflection.MethodBase;
            }
            else
            {
                // We have a group! Find the overload that we're after (no args were passed here):
                resolvedMethod = group.Match(null);
            }

            // Create a FunctionCallExpr.
            FunctionCallExpression function = new FunctionCallExpression(Operator.FunctionCall);

            // Apply resolved:
            function.ResolvedMethod = resolvedMethod;

            // Apply target:
            function.Push(operand);

            // Overwrite local operand:
            SetRawOperand(0, function);

            return(function);
        }
示例#22
0
 /// <summary>
 /// Parses the source text into an abstract syntax tree.
 /// </summary>
 public override void Parse(OptimizationInfo optimizationInfo)
 {
     using (var lexer = new Lexer(this.Engine, this.Source))
     {
         var parser = new Parser(this.Engine, lexer, this.InitialScope, optimizationInfo, this.Options, CodeContext.Global);
         this.AbstractSyntaxTree      = parser.Parse();
         this.StrictMode              = parser.StrictMode;
         this.MethodOptimizationHints = parser.MethodOptimizationHints;
     }
 }
示例#23
0
        /// <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)
        {
            // Inserts a breakpoint into the IL.
            generator.Breakpoint();

            // When the debugger stops, it stops at the first instruction after the breakpoint.  By
            // inserting a no-op operation the debugger will highlight the "debugger" statement
            // instead of the statement after the "debugger" statement.
            generator.NoOperation();
        }
示例#24
0
        public void TryApplyConstant(OptimizationInfo optimizationInfo, bool isConst)
        {
            // Try loading a constant now:
            Variable v = ResolvedProperty;

            if (v != null)
            {
                v.IsConstant = isConst;
            }
        }
示例#25
0
        /// <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, "SyntaxError", string.Format("Cannot delete {0} because deleting a variable or argument is not allowed in strict mode", this.Name), 1, optimizationInfo.Source.Path, optimizationInfo.FunctionName);
            }

            // Always just false:
            generator.LoadBoolean(false);
        }
示例#26
0
        /// <summary>Updates the type of the property variable. Note that this does nothing if the property
        /// is fixed; i.e. it's built in.</summary>
        public void ApplyType(OptimizationInfo optimizationInfo, Type type)
        {
            if (ResolvedProperty == null)
            {
                // Unable to set it.
                return;
            }

            // Set the type:
            ResolvedProperty.Type = type;
        }
示例#27
0
        public object TryApplyConstant(OptimizationInfo optimizationInfo, Expression expr)
        {
            // Try loading a constant now:
            Variable v = Variable;

            if (v != null && v.TryLoadConstant(expr))
            {
                return(v.ConstantValue);
            }

            return(null);
        }
示例#28
0
 /// <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)
 {
     // Emit code to throw the given value.
     EmitHelpers.LoadEngine(generator);
     this.Value.GenerateCode(generator, optimizationInfo);
     EmitConversion.ToAny(generator, this.Value.GetResultType(optimizationInfo));
     generator.LoadInt32(1);
     generator.LoadStringOrNull(optimizationInfo.Source.Path);
     generator.LoadStringOrNull(optimizationInfo.FunctionName);
     generator.NewObject(ReflectionHelpers.JavaScriptException_Constructor_Object);
     generator.Throw();
 }
示例#29
0
        /// <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)
        {
                        #warning change this.

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

            // 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].GetResultType(optimizationInfo));
                generator.StoreArrayElement(typeof(object));
            }
        }
示例#30
0
        /// <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.

            // Store the value.
            target.GenerateSet(generator, optimizationInfo, optimizationInfo.RootExpression != this, target.GetResultType(optimizationInfo) == typeof(int) ? typeof(int) : typeof(double), delegate(bool two)
            {
                // Get the target value.
                target.GenerateGet(generator, optimizationInfo, true);

                // Convert it to a number.
                if (target.GetResultType(optimizationInfo) != typeof(int))
                {
                    EmitConversion.ToNumber(generator, target.GetResultType(optimizationInfo));
                }

                // If this is PostIncrement or PostDecrement, duplicate the value so it can be produced as the return value.
                if (postfix && two)
                {
                    generator.Duplicate();
                }

                // Load the increment constant.
                if (target.GetResultType(optimizationInfo) == typeof(int))
                {
                    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, duplicate the value so it can be produced as the return value.
                if (!postfix && two)
                {
                    generator.Duplicate();
                }
            }, optimizationInfo.StrictMode);
        }