예제 #1
0
        internal override System.Linq.Expressions.Expression TryCompile(bool selfCompile, bool forAssign, Type expectedType, List <CodeNode> dynamicValues)
        {
            dynamicValues.Add(this);
            var res = System.Linq.Expressions.Expression.Call(
                System.Linq.Expressions.Expression.ArrayAccess(JITHelpers.DynamicValuesParameter, JITHelpers.cnst(dynamicValues.Count - 1)),
                forAssign ? JITHelpers.EvaluateForWriteMethod : JITHelpers.EvaluateMethod,
                JITHelpers.ContextParameter
                );

            if (expectedType == typeof(int))
            {
                res = System.Linq.Expressions.Expression.Call(JITHelpers.JSObjectToInt32Method, res);
            }
            return(res);
        }
예제 #2
0
        public override bool Build(ref CodeNode _this, int expressionDepth, Dictionary <string, VariableDescriptor> variables, CodeContext codeContext, InternalCompilerMessageCallback message, FunctionInfo stats, Options opts)
        {
            if (built)
            {
                return(false);
            }
            built = true;

            List <VariableDescriptor> variablesToRestore = null;

            if (_variables != null && _variables.Length != 0)
            {
                for (var i = 0; i < _variables.Length; i++)
                {
                    VariableDescriptor desc = null;
                    if (variables.TryGetValue(_variables[i].name, out desc) && desc.definitionScopeLevel < _variables[i].definitionScopeLevel)
                    {
                        if (variablesToRestore == null)
                        {
                            variablesToRestore = new List <VariableDescriptor>();
                        }
                        variablesToRestore.Add(desc);
                    }

                    variables[_variables[i].name] = _variables[i];

                    _variables[i].owner = this;
                }

                for (var i = 0; i < _variables.Length; i++)
                {
                    Parser.Build(
                        ref _variables[i].initializer,
                        System.Math.Max(2, expressionDepth),
                        variables,
                        codeContext | (this._strict ? CodeContext.Strict : CodeContext.None),
                        message,
                        stats,
                        opts);
                }
            }

            for (var i = 0; i < _lines.Length; i++)
            {
                var ed = _lines[i] as EntityDefinition;
                if (ed != null && ed.Hoist)
                {
                    _lines[i] = null;
                }
            }

            bool unreachable = false;

            for (int i = 0; i < _lines.Length; i++)
            {
                if (_lines[i] != null)
                {
                    if (_lines[i] is Empty)
                    {
                        _lines[i] = null;
                    }
                    else
                    {
                        if (unreachable && message != null)
                        {
                            message(MessageLevel.CriticalWarning, _lines[i].Position, _lines[i].Length, "Unreachable code detected.");
                        }
                        var cn = _lines[i];
                        Parser.Build(ref cn, (codeContext & CodeContext.InEval) != 0 ? 2 : System.Math.Max(1, expressionDepth), variables, codeContext | (this._strict ? CodeContext.Strict : CodeContext.None), message, stats, opts);
                        if (cn is Empty)
                        {
                            _lines[i] = null;
                        }
                        else
                        {
                            _lines[i] = cn;
                        }
                        unreachable |= cn is Return || cn is Break || cn is Continue || cn is Throw;
                    }
                }
            }

            int f = _lines.Length, t = _lines.Length - 1;

            for (; f-- > 0;)
            {
                if (_lines[f] != null && _lines[t] == null)
                {
                    _lines[t] = _lines[f];
                    _lines[f] = null;
                }
                if (_lines[t] != null)
                {
                    t--;
                }
            }

            if (expressionDepth > 0 && (_variables == null || _variables.Length == 0))
            {
                if (_lines.Length == 0)
                {
                    _this = Empty.Instance;
                }
            }
            else
            {
                if (message != null)
                {
                    for (var i = 0; i < _variables.Length; i++)
                    {
                        if (_variables[i].ReferenceCount == 1)
                        {
                            message(
                                MessageLevel.Recomendation,
                                _variables[i].references[0].Position,
                                0,
                                "Unused variable \"" + _variables[i].name + "\"");
                        }
                        else
                        {
                            break;
                        }
                    }
                }
#if (NET40 || INLINE) && JIT
                compiledVersion = JITHelpers.compile(this, depth >= 0);
#endif
            }

            if (t >= 0 && this == _this)
            {
                var newBody = new CodeNode[_lines.Length - t - 1];
                f = 0;
                while (++t < _lines.Length)
                {
                    newBody[f++] = _lines[t];
                }
                _lines = newBody;
            }

            if (_variables != null && _variables.Length != 0)
            {
                for (var i = 0; i < _variables.Length; i++)
                {
                    variables.Remove(_variables[i].name);
                }
            }

            if (variablesToRestore != null)
            {
                for (var i = 0; i < variablesToRestore.Count; i++)
                {
                    variables[variablesToRestore[i].name] = variablesToRestore[i];
                }
            }

            return(false);
        }