void AddPropertyForDuplicates(string name, CompiledDataContextDescriptor contextDescriptor)
        {
            CodeMemberProperty accessorProperty = new CodeMemberProperty();
            accessorProperty.Attributes = MemberAttributes.Family | MemberAttributes.Final;
            accessorProperty.Name = name;
            accessorProperty.Type = new CodeTypeReference(typeof(object));

            CodeThrowExceptionStatement exception = new CodeThrowExceptionStatement(
                new CodeObjectCreateExpression(typeof(InvalidOperationException), new CodePrimitiveExpression(SR.CompiledExpressionsDuplicateName(name))));

            accessorProperty.GetStatements.Add(exception);
            accessorProperty.SetStatements.Add(exception);

            contextDescriptor.CodeTypeDeclaration.Members.Add(accessorProperty);

            //
            // Create another property for the read only class.
            // This will only have a getter so we can't just re-use the property from above
            CodeMemberProperty accessorPropertyForReadOnly = new CodeMemberProperty();
            accessorPropertyForReadOnly.Attributes = MemberAttributes.Family | MemberAttributes.Final;
            accessorPropertyForReadOnly.Name = name;
            accessorPropertyForReadOnly.Type = new CodeTypeReference(typeof(object));
            //
            // OK to share the exception from above
            accessorPropertyForReadOnly.GetStatements.Add(exception);

            contextDescriptor.CodeTypeDeclarationForReadOnly.Members.Add(accessorPropertyForReadOnly);
        }
        void GenerateField(MemberData memberData, CompiledDataContextDescriptor contextDescriptor)
        {
            if (contextDescriptor.Duplicates.Contains(memberData.Name))
            {
                return;
            }

            CodeMemberField accessorField = new CodeMemberField();
            accessorField.Attributes = MemberAttributes.Family | MemberAttributes.Final;
            accessorField.Name = memberData.Name;
            accessorField.Type = new CodeTypeReference(memberData.Type);

            if (IsRedefinition(memberData.Name))
            {
                accessorField.Attributes |= MemberAttributes.New;
            }

            contextDescriptor.CodeTypeDeclaration.Members.Add(accessorField);

            contextDescriptor.CodeTypeDeclarationForReadOnly.Members.Add(accessorField);
        }
        void GenerateProperty(MemberData memberData, CompiledDataContextDescriptor contextDescriptor)
        {
            if (contextDescriptor.Duplicates.Contains(memberData.Name))
            {
                return;
            }

            bool isRedefinition = IsRedefinition(memberData.Name);

            CodeMemberProperty accessorProperty = GenerateCodeMemberProperty(memberData, isRedefinition);

            //
            // Generate a get accessor that looks like this:
            // return (Foo) this.GetVariableValue(contextId, locationIndexId)
            CodeMethodReturnStatement getterStatement = new CodeMethodReturnStatement(
                new CodeCastExpression(memberData.Type, new CodeMethodInvokeExpression(
                    new CodeMethodReferenceExpression(
                        new CodeThisReferenceExpression(),
                        "GetVariableValue"), 
                        new CodeBinaryOperatorExpression(
                        new CodePrimitiveExpression(memberData.Index), 
                        CodeBinaryOperatorType.Add, 
                        new CodeVariableReferenceExpression("locationsOffset")))));

            accessorProperty.GetStatements.Add(getterStatement);
            
            // Generate a set accessor that looks something like this:
            // this.SetVariableValue(contextId, locationIndexId, value)
            accessorProperty.SetStatements.Add(new CodeMethodInvokeExpression(
                new CodeMethodReferenceExpression(
                    new CodeThisReferenceExpression(),
                    "SetVariableValue"),
                     new CodeBinaryOperatorExpression(
                        new CodePrimitiveExpression(memberData.Index),
                        CodeBinaryOperatorType.Add,
                        new CodeVariableReferenceExpression("locationsOffset")),
                    new CodePropertySetValueReferenceExpression()));

            contextDescriptor.CodeTypeDeclaration.Members.Add(accessorProperty);

            //
            // Create another property for the read only class.
            // This will only have a getter so we can't just re-use the property from above
            CodeMemberProperty accessorPropertyForReadOnly = GenerateCodeMemberProperty(memberData, isRedefinition);
            //
            // OK to share the getter statement from above
            accessorPropertyForReadOnly.GetStatements.Add(getterStatement);

            contextDescriptor.CodeTypeDeclarationForReadOnly.Members.Add(accessorPropertyForReadOnly);
        }
        void AddMember(string name, Type type, CompiledDataContextDescriptor contextDescriptor)
        {
            if (IsValidTextIdentifierName(name))
            {
                //
                // These checks will be invariantlowercase if the language is VB
                if (contextDescriptor.Fields.ContainsKey(name) || contextDescriptor.Properties.ContainsKey(name))
                {
                    if (!contextDescriptor.Duplicates.Contains(name))
                    {
                        contextDescriptor.Duplicates.Add(name.ToUpperInvariant());
                    }
                }
                else
                {
                    MemberData memberData = new MemberData();
                    memberData.Type = type;
                    memberData.Name = name;
                    memberData.Index = contextDescriptor.NextMemberIndex;

                    if (type.IsValueType)
                    {
                        contextDescriptor.Fields.Add(name, memberData);
                    }
                    else
                    {
                        contextDescriptor.Properties.Add(name, memberData);
                    }
                }
            }
            //
            // Regardless of whether or not this member name is an invalid, duplicate, or valid identifier
            // always increment the member count so that the indexes we generate always match
            // the list that the runtime gives to the ITextExpression
            // The exception here is if the name is null
            if (name != null)
            {
                contextDescriptor.NextMemberIndex++;
            }
        }
        void GenerateMembers(CompiledDataContextDescriptor descriptor)
        {
            foreach (KeyValuePair<string, MemberData> property in descriptor.Properties)
            {
                GenerateProperty(property.Value, descriptor);
            }

            if (descriptor.Fields.Count > 0)
            {
                foreach (KeyValuePair<string, MemberData> field in descriptor.Fields)
                {
                    GenerateField(field.Value, descriptor);
                }

                CodeMemberMethod getValueTypeValuesMethod = GenerateGetValueTypeValues(descriptor);

                descriptor.CodeTypeDeclaration.Members.Add(getValueTypeValuesMethod);
                descriptor.CodeTypeDeclaration.Members.Add(GenerateSetValueTypeValues(descriptor));

                descriptor.CodeTypeDeclarationForReadOnly.Members.Add(getValueTypeValuesMethod);
            }

            if (descriptor.Duplicates.Count > 0 && this.IsVB)
            {
                foreach (string duplicate in descriptor.Duplicates)
                {
                    AddPropertyForDuplicates(duplicate, descriptor);
                }
            }
        }
        void OnRootImplementationScope(Activity activity, out CompiledDataContextDescriptor rootArgumentAccessorContext)
        {
            Fx.Assert(this.compiledDataContexts.Count == 2, "The stack of data contexts should contain the root argument default expression and accessor contexts");

            rootArgumentAccessorContext = this.compiledDataContexts.Pop();

            if (activity.RuntimeVariables != null && activity.RuntimeVariables.Count > 0)
            {
                this.OnVariableScope(activity);
            }
        }
        void OnAfterRootImplementationScope(Activity activity, CompiledDataContextDescriptor rootArgumentAccessorContext)
        {
            if (activity.RuntimeVariables != null && activity.RuntimeVariables.Count > 0)
            {
                OnAfterVariableScope();
            }

            this.compiledDataContexts.Push(rootArgumentAccessorContext);
        }
        void GenerateValidate(CompiledDataContextDescriptor descriptor, bool forReadOnly)
        {
            //
            //
            // Validate the locations at runtime match the set at compile time
            //
            // protected override bool Validate(IList<LocationReference> locationReferences)
            // {
            //   if (validateLocationCount && locationReferences.Count != [generated count of location references])
            //   {
            //     return false;
            //   }
            //   if (locationReferences[0].Name != [generated name for index] ||
            //       locationReferences[0].Type != typeof([generated type for index]))
            //   {
            //     return false;
            //   }
            //
            //   ...
            //
            // }
            CodeMemberMethod validateMethod = new CodeMemberMethod();
            validateMethod.Name = "Validate";
            validateMethod.Attributes = MemberAttributes.Public | MemberAttributes.Static;

            if (this.compiledDataContexts.Count > 0)
            {
                validateMethod.Attributes |= MemberAttributes.New;
            }


            validateMethod.ReturnType = new CodeTypeReference(typeof(bool));

            validateMethod.Parameters.Add(
                new CodeParameterDeclarationExpression(
                    new CodeTypeReference(typeof(IList<LocationReference>)),
                    "locationReferences"));

            validateMethod.Parameters.Add(
                new CodeParameterDeclarationExpression(
                    new CodeTypeReference(typeof(bool)),
                    "validateLocationCount"));

            validateMethod.Parameters.Add(
               new CodeParameterDeclarationExpression(
                   new CodeTypeReference(typeof(int)),
                   "offset") );

            CodeBinaryOperatorExpression shouldCheckLocationCountExpression = new CodeBinaryOperatorExpression(
                new CodeVariableReferenceExpression("validateLocationCount"),
                CodeBinaryOperatorType.ValueEquality,
                new CodePrimitiveExpression(true));

            CodeBinaryOperatorExpression compareLocationCountExpression = new CodeBinaryOperatorExpression(
                    new CodePropertyReferenceExpression(
                    new CodeVariableReferenceExpression("locationReferences"),            
                    "Count"),
                    CodeBinaryOperatorType.LessThan,
                    new CodePrimitiveExpression(descriptor.NextMemberIndex)
                    );

            CodeBinaryOperatorExpression checkLocationCountExpression = new CodeBinaryOperatorExpression(
                shouldCheckLocationCountExpression,
                CodeBinaryOperatorType.BooleanAnd,
                compareLocationCountExpression);

            CodeConditionStatement checkLocationCountStatement = new CodeConditionStatement(
                checkLocationCountExpression,
                new CodeMethodReturnStatement(
                    new CodePrimitiveExpression(false)));

            validateMethod.Statements.Add(checkLocationCountStatement);

            if (descriptor.NextMemberIndex > 0)
            {
                CodeConditionStatement generateNewOffset = new CodeConditionStatement(shouldCheckLocationCountExpression,
                    new CodeStatement[] 
                {
                    new CodeAssignStatement(new CodeVariableReferenceExpression("offset"), 
                    new CodeBinaryOperatorExpression(
                        new CodePropertyReferenceExpression(new CodeVariableReferenceExpression("locationReferences"), "Count"),
                        CodeBinaryOperatorType.Subtract,
                        new CodePrimitiveExpression(descriptor.NextMemberIndex)))
                });
                validateMethod.Statements.Add(generateNewOffset);
            }

            CodeAssignStatement setexpectedLocationsCountStatement = new CodeAssignStatement(
                new CodeVariableReferenceExpression("expectedLocationsCount"),
                new CodePrimitiveExpression(descriptor.NextMemberIndex));

            validateMethod.Statements.Add(setexpectedLocationsCountStatement);

            foreach (KeyValuePair<string, MemberData> kvp in descriptor.Properties)
            {
                validateMethod.Statements.Add(GenerateLocationReferenceCheck(kvp.Value));
            }

            foreach (KeyValuePair<string, MemberData> kvp in descriptor.Fields)
            {
                validateMethod.Statements.Add(GenerateLocationReferenceCheck(kvp.Value));
            }
                        
            if (this.compiledDataContexts.Count >= 1)
            {
                CompiledDataContextDescriptor baseDescriptor = this.compiledDataContexts.Peek();
                CodeTypeDeclaration baseType = forReadOnly ? baseDescriptor.CodeTypeDeclarationForReadOnly : baseDescriptor.CodeTypeDeclaration;

                CodeMethodInvokeExpression invokeBase = new CodeMethodInvokeExpression(
                    new CodeMethodReferenceExpression(
                        new CodeTypeReferenceExpression(baseType.Name),
                        "Validate"),
                    new CodeVariableReferenceExpression("locationReferences"),
                    new CodePrimitiveExpression(false),
                    new CodeVariableReferenceExpression("offset"));

                validateMethod.Statements.Add(
                    new CodeMethodReturnStatement(invokeBase));
            }
            else
            {
                validateMethod.Statements.Add(
                    new CodeMethodReturnStatement(
                        new CodePrimitiveExpression(true)));
            }

            if (forReadOnly)
            {
                descriptor.CodeTypeDeclarationForReadOnly.Members.Add(validateMethod);
            }
            else
            {
                descriptor.CodeTypeDeclaration.Members.Add(validateMethod);
            }
        }
 CompiledDataContextDescriptor PushDataContextDescriptor()
 {
     CompiledDataContextDescriptor contextDescriptor = new CompiledDataContextDescriptor(() => this.IsVB)
     {
         CodeTypeDeclaration = GenerateCompiledDataContext(false),
         CodeTypeDeclarationForReadOnly = GenerateCompiledDataContext(true),
         NextMemberIndex = GetStartMemberIndex()
     };
     this.compiledDataContexts.Push(contextDescriptor);
     this.nextContextId++;
     
     return contextDescriptor;
 }
        CodeMemberMethod GenerateSetValueTypeValues(CompiledDataContextDescriptor descriptor)
        {
            CodeMemberMethod pushMethod = new CodeMemberMethod();
            pushMethod.Name = setValueTypeValuesString;
            pushMethod.Attributes = MemberAttributes.Override | MemberAttributes.Family;

            foreach (KeyValuePair<string, MemberData> valueField in descriptor.Fields)
            {
                if (descriptor.Duplicates.Contains(valueField.Key))
                {
                    continue;
                }

                CodeMethodInvokeExpression setValue = new CodeMethodInvokeExpression(
                    new CodeMethodReferenceExpression(
                        new CodeThisReferenceExpression(),
                        "SetVariableValue"),
                        new CodeBinaryOperatorExpression(
                        new CodePrimitiveExpression(valueField.Value.Index),
                        CodeBinaryOperatorType.Add, 
                        new CodeVariableReferenceExpression("locationsOffset")),
                        new CodeFieldReferenceExpression(
                            new CodeThisReferenceExpression(), valueField.Key));
                
                pushMethod.Statements.Add(setValue);
            }

            pushMethod.Statements.Add(new CodeMethodInvokeExpression(
                new CodeMethodReferenceExpression(
                    new CodeBaseReferenceExpression(),
                    pushMethod.Name)));

            return pushMethod;
        }
        void GenerateExpressionGetTreeMethod(Activity activity, CompiledExpressionDescriptor expressionDescriptor, CompiledDataContextDescriptor dataContextDescriptor, bool isValue, bool isStatement, int nextExpressionId)
        {
            CodeMemberMethod expressionMethod = new CodeMemberMethod();
            expressionMethod.Attributes = MemberAttributes.Assembly | MemberAttributes.Final;
            expressionMethod.Name = string.Format(CultureInfo.InvariantCulture, expressionGetTreeString, nextExpressionId);
            expressionMethod.ReturnType = new CodeTypeReference(typeof(Expression));
            expressionDescriptor.GetExpressionTreeMethodName = expressionMethod.Name;

            if (isStatement)
            {
                // Can't generate expression tree for a statement
                expressionMethod.Statements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(null)));
                dataContextDescriptor.CodeTypeDeclaration.Members.Add(expressionMethod);
                return;
            }

            string coreExpressionText = expressionDescriptor.ExpressionText;
            CodeLinePragma pragma;
            AlignText(activity, ref coreExpressionText, out pragma);

            Type returnType = typeof(Expression<>).MakeGenericType(typeof(Func<>).MakeGenericType(expressionDescriptor.ResultType));
            string expressionText = null;
            if (IsVB)
            {
                expressionText = string.Concat(vbLambdaString, coreExpressionText);
            }
            else if (IsCS)
            {
                expressionText = string.Concat(csharpLambdaString, coreExpressionText);
            }

            if (expressionText != null)
            {
                CodeVariableDeclarationStatement statement = new CodeVariableDeclarationStatement(returnType, "expression", new CodeSnippetExpression(expressionText));
                statement.LinePragma = pragma;
                expressionMethod.Statements.Add(statement);

                CodeMethodInvokeExpression invokeExpression = new CodeMethodInvokeExpression(
                    new CodeBaseReferenceExpression(),
                    "RewriteExpressionTree",
                    new CodeExpression[] { new CodeVariableReferenceExpression("expression") });

                expressionMethod.Statements.Add(new CodeMethodReturnStatement(invokeExpression));
            }
            else
            {
                expressionMethod.Statements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(null)));
            }            

            if (isValue)
            {
                dataContextDescriptor.CodeTypeDeclarationForReadOnly.Members.Add(expressionMethod);
            }
            else
            {
                dataContextDescriptor.CodeTypeDeclaration.Members.Add(expressionMethod);
            }            
        }
        bool TryGenerateExpressionCode(Activity activity, CompiledDataContextDescriptor dataContextDescriptor, int nextExpressionId, string language)
        {
            ITextExpression textExpression = (ITextExpression)activity;
            if (!TextExpression.LanguagesAreEqual(textExpression.Language, language)
                || string.IsNullOrWhiteSpace(textExpression.ExpressionText))
            {
                //
                // We can only compile expressions that match the project's flavor
                // and expression activities with no expressions don't need anything generated.
                return false;
            }

            Type resultType = (activity is ActivityWithResult) ? ((ActivityWithResult)activity).ResultType : null;

            string expressionText = textExpression.ExpressionText;
                        
            bool isReference = false;
            bool isValue = false;
            bool isStatement = false;

            if (resultType == null)
            {
                isStatement = true;
            }
            else
            {
                isReference = TypeHelper.AreTypesCompatible(resultType, typeof(Location));
                isValue = !isReference;
            }

            CodeTypeDeclaration typeDeclaration;
            if (isValue)
            {
                typeDeclaration = dataContextDescriptor.CodeTypeDeclarationForReadOnly;
            }
            else
            {
                //
                // Statement and reference get read/write context
                typeDeclaration = dataContextDescriptor.CodeTypeDeclaration;
            }
             
            CompiledExpressionDescriptor descriptor = new CompiledExpressionDescriptor();
            descriptor.TypeName = typeDeclaration.Name;
            descriptor.Id = nextExpressionId;
            descriptor.ExpressionText = textExpression.ExpressionText;
            
            if (isReference)
            {
                if (resultType.IsGenericType)
                {
                    resultType = resultType.GetGenericArguments()[0];
                }
                else
                {
                    resultType = typeof(object);
                }
            }

            descriptor.ResultType = resultType;
            
            GenerateExpressionGetTreeMethod(activity, descriptor, dataContextDescriptor, isValue, isStatement, nextExpressionId);

            if (isValue || isReference)
            {
                CodeMemberMethod expressionGetMethod = GenerateGetMethod(activity, resultType, expressionText, nextExpressionId);
                typeDeclaration.Members.Add(expressionGetMethod);

                CodeMemberMethod expressionGetValueTypeAccessorMethod = GenerateGetMethodWrapper(expressionGetMethod);
                typeDeclaration.Members.Add(expressionGetValueTypeAccessorMethod);

                descriptor.GetMethodName = expressionGetValueTypeAccessorMethod.Name;
            }

            if (isReference)
            {
                CodeMemberMethod expressionSetMethod = GenerateSetMethod(activity, resultType, expressionText, nextExpressionId);
                dataContextDescriptor.CodeTypeDeclaration.Members.Add(expressionSetMethod);

                CodeMemberMethod expressionSetValueTypeAccessorMethod = GenerateSetMethodWrapper(expressionSetMethod);
                dataContextDescriptor.CodeTypeDeclaration.Members.Add(expressionSetValueTypeAccessorMethod);

                descriptor.SetMethodName = expressionSetValueTypeAccessorMethod.Name;
            }

            if (isStatement)
            {
                CodeMemberMethod statementMethod = GenerateStatementMethod(activity, expressionText, nextExpressionId);
                dataContextDescriptor.CodeTypeDeclaration.Members.Add(statementMethod);

                CodeMemberMethod expressionSetValueTypeAccessorMethod = GenerateStatementMethodWrapper(statementMethod);
                dataContextDescriptor.CodeTypeDeclaration.Members.Add(expressionSetValueTypeAccessorMethod);

                descriptor.StatementMethodName = expressionSetValueTypeAccessorMethod.Name;
            }

            expressionDescriptors.Add(descriptor);

            return true;
        }