Ejemplo n.º 1
0
        internal override void ResolveVariables(OptimizationInfo optimizationInfo)
        {
            if (ResolvedProperty != null || propertyName != null)
            {
                // Already resolved.
                return;
            }

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

            // Right-hand-side can be a property name (a.b)
            if (this.OperatorType == OperatorType.MemberAccess)
            {
                var rhs = this.GetOperand(1) as NameExpression;
                if (rhs == null)
                {
                    throw new JavaScriptException(optimizationInfo.Engine, "SyntaxError", "Invalid member access", 1, optimizationInfo.Source.Path, optimizationInfo.FunctionName);
                }
                propertyName = rhs.Name;
            }

            // Or a constant indexer (a['b'])
            if (this.OperatorType == OperatorType.Index)
            {
                var rhs = this.GetOperand(1);
                if (rhs != null)
                {
                    Type rhsType = rhs.GetResultType(optimizationInfo);

                    if (rhsType == typeof(string))
                    {
                        // Try a literal:
                        LiteralExpression literalStr = rhs as LiteralExpression;

                        if (literalStr != null)
                        {
                            propertyName = TypeConverter.ToString(literalStr.Value);

                            // Could actually be numeric, so try that:
                            if (propertyName != null && Nitrassic.Library.Array.ParseArrayIndex(propertyName) != uint.MaxValue)
                            {
                                // Yep, it is!
                                isArrayIndex = true;
                            }
                        }
                    }
                    else if (PrimitiveTypeUtilities.IsNumeric(rhsType))
                    {
                        // array index (a[0])
                        isArrayIndex = true;
                    }
                }
            }

            if (isArrayIndex == true)
            {
                // Array indexer
                // -------------
                // xxx = object[index]

                // Load the left-hand side and convert to an object instance.
                var lhs = this.GetOperand(0);

                // Get the type of the LHS (the object being read from):
                Type lhsType = lhs.GetResultType(optimizationInfo);

                // Get the proto for it:
                Nitrassic.Library.Prototype proto = optimizationInfo.Engine.Prototypes.Get(lhsType);

                // Does that type have an indexer method on it? (this[uint])
                ResolvedProperty = proto.Indexer(typeof(uint));

                if (ResolvedProperty == null)
                {
                    // Try [int] instead:
                    ResolvedProperty = proto.Indexer(typeof(int));
                }
            }

            if (ResolvedProperty == null && propertyName != null)
            {
                // Load the left-hand side and convert to an object instance.
                var lhs = this.GetOperand(0);

                Type lhsType = lhs.GetResultType(optimizationInfo);

                // Get the prototype:
                Nitrassic.Library.Prototype proto = optimizationInfo.Engine.Prototypes.Get(lhsType);

                // Get the property:
                ResolvedProperty = proto.GetProperty(propertyName);

                if (ResolvedProperty == null)
                {
                    // Add it now (as undefined):
                    ResolvedProperty = proto.AddProperty(propertyName, null, Nitrassic.Library.PropertyAttributes.FullAccess);
                }
            }
        }