private IEnumerable <JsStatement> CreateNamespaces(JsExpression root, IEnumerable <string> requiredNamespaces)
 {
     return(requiredNamespaces.SelectMany(EntireNamespaceHierarchy)
            .Distinct()
            .OrderBy(ns => ns)
            .Select(ns => {
         var access = MakeNestedMemberAccess(ns, root);
         return (JsStatement)JsExpression.Assign(access, JsExpression.LogicalOr(access, JsExpression.ObjectLiteral()));
     }));
 }
        private JsExpression GetFieldHashCode(IField field)
        {
            var impl = _metadataImporter.GetFieldSemantics(field);

            if (impl.Type != FieldScriptSemantics.ImplType.Field)
            {
                return(null);
            }

            IType        type          = NullableType.GetUnderlyingType(field.Type);
            bool         needNullCheck = field.Type.IsReferenceType != false || field.Type.IsKnownType(KnownTypeCode.NullableOfT) || type.Kind == TypeKind.Enum && MetadataUtils.IsNamedValues(field.Type.GetDefinition(), _attributeStore);
            JsExpression member        = JsExpression.Member(JsExpression.This, impl.Name);

            JsExpression result = JsExpression.Invocation(JsExpression.Member(_systemScript, "getHashCode"), member);

            if (needNullCheck)
            {
                result = JsExpression.Conditional(member, result, JsExpression.Number(0));
            }

            if (type.Kind == TypeKind.Enum && !MetadataUtils.IsNamedValues(type.GetDefinition(), _attributeStore))
            {
                result = needNullCheck ? JsExpression.LogicalOr(member, JsExpression.Number(0)) : member;
            }
            else if (type is ITypeDefinition)
            {
                switch (((ITypeDefinition)type).KnownTypeCode)
                {
                case KnownTypeCode.Boolean:
                    result = JsExpression.Conditional(member, JsExpression.Number(1), JsExpression.Number(0));
                    break;

                case KnownTypeCode.Byte:
                case KnownTypeCode.SByte:
                case KnownTypeCode.Char:
                case KnownTypeCode.Int16:
                case KnownTypeCode.UInt16:
                case KnownTypeCode.Int32:
                case KnownTypeCode.UInt32:
                case KnownTypeCode.Int64:
                case KnownTypeCode.UInt64:
                case KnownTypeCode.Decimal:
                case KnownTypeCode.Single:
                case KnownTypeCode.Double:
                    result = needNullCheck ? JsExpression.LogicalOr(member, JsExpression.Number(0)) : member;
                    break;
                }
            }

            return(result);
        }
        private bool HandleSwitchStatement(JsSwitchStatement stmt, StackEntry location, ImmutableStack <StackEntry> stack, ImmutableStack <Tuple <string, State> > breakStack, ImmutableStack <Tuple <string, State> > continueStack, State currentState, State returnState, IList <JsStatement> currentBlock)
        {
            var          stateAfter = GetStateAfterStatement(location, stack, currentState.FinallyStack, returnState);
            JsExpression expression = stmt.Expression;

            if (_isExpressionComplexEnoughForATemporaryVariable(expression))
            {
                string newName = _allocateTempVariable();
                currentBlock.Add(JsStatement.Var(newName, expression));
                expression = JsExpression.Identifier(newName);
            }

            var         clauses                 = new List <Tuple <JsExpression, JsBlockStatement> >();
            JsStatement defaultClause           = null;
            State?      currentFallthroughState = null;

            for (int i = 0; i < stmt.Sections.Count; i++)
            {
                var clause = stmt.Sections[i];

                var origBody = new List <JsStatement>();
                origBody.AddRange(clause.Body.Statements);

                State?nextFallthroughState;

                if (i < stmt.Sections.Count - 1 && (origBody.Count == 0 || IsNextStatementReachable(origBody[origBody.Count - 1])))
                {
                    // Fallthrough
                    var nextBody = stmt.Sections[i + 1].Body.Statements;
                    if (nextBody.Count > 0 && nextBody[0] is JsLabelledStatement)
                    {
                        nextFallthroughState = GetOrCreateStateForLabel(((JsLabelledStatement)nextBody[0]).Label, currentState.FinallyStack);
                    }
                    else
                    {
                        nextFallthroughState = CreateNewStateValue(currentState.FinallyStack);
                    }
                }
                else
                {
                    nextFallthroughState = null;
                }

                breakStack = breakStack.Push(Tuple.Create(GetLabelForState(currentState), stateAfter.Item1));

                IList <JsStatement> body;
                if (currentFallthroughState != null)
                {
                    body = new List <JsStatement>();
                    body.Add(new JsGotoStateStatement(currentFallthroughState.Value, currentState));
                    Enqueue(ImmutableStack <StackEntry> .Empty.Push(new StackEntry(JsStatement.Block(origBody), 0)), breakStack, continueStack, currentFallthroughState.Value, stateAfter.Item1);
                }
                else
                {
                    body = Handle(ImmutableStack <StackEntry> .Empty.Push(new StackEntry(JsStatement.Block(origBody), 0)), breakStack, continueStack, currentState, nextFallthroughState ?? stateAfter.Item1, false, false);
                }

                if (clause.Values.Any(v => v == null))
                {
                    defaultClause = JsStatement.Block(body);
                }
                else
                {
                    JsExpression test = clause.Values.Select(v => JsExpression.Same(expression, v)).Aggregate((o, e) => o != null ? JsExpression.LogicalOr(o, e) : e);
                    clauses.Add(Tuple.Create(test, JsStatement.Block(body)));
                }

                currentFallthroughState = nextFallthroughState;
            }
            clauses.Reverse();

            currentBlock.Add(clauses.Where(c => c.Item1 != null).Aggregate(defaultClause, (o, n) => JsStatement.If(n.Item1, n.Item2, o)));
            currentBlock.Add(new JsGotoStateStatement(stateAfter.Item1, currentState));

            if (stateAfter.Item2)
            {
                Enqueue(PushFollowing(stack, location), breakStack, continueStack, stateAfter.Item1, returnState);
                return(false);
            }

            return(true);
        }