Ejemplo n.º 1
0
 public void Visit(InnerJoinStatement statement, CommonTree tree)
 {
     Parent(tree).Children.Add(statement);
     SetLine(statement, tree);
     VisitChildren(tree);
 }
        public void Visit(InnerJoinStatement statement)
        {
            CodeMemberMethod method = new CodeMemberMethod();
            method.Name = "Join_" + Guid.NewGuid().ToString("N");
            method.Attributes = MemberAttributes.Private;
            method.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference("IEnumerable", _codeStack.Peek().Scope.CodeDomReference), "outer"));
            GenerateCallStatement(method.Statements, statement.Line.Line);
            _mainType.Type.Members.Add(method);

            CodeTypeReference fetchAnonType;
            var fetchMethod = CreateFetch(statement, out fetchAnonType);
            method.Statements.Add(new CodeVariableDeclarationStatement(new CodeTypeReference("IEnumerable", fetchAnonType), "table",
                   new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(null, fetchMethod.Name))));

            //create combined anon type
            var anon = "anon_" + Guid.NewGuid().ToString("N");
            var bufferTable = new CodeTypeDeclaration(anon) { TypeAttributes = TypeAttributes.NestedPrivate };
            bufferTable.BaseTypes.Add(new CodeTypeReference("IRow"));
            _mainType.Type.Members.Add(bufferTable);
            bufferTable.Members.AddRange(_joinMembers.ToArray());

            //Do Join
            var anonType = new CodeTypeReference(anon);

            method.Statements.Add(new CodeVariableDeclarationStatement(new CodeTypeReference("IList", anonType), "join",
                new CodeObjectCreateExpression(new CodeTypeReference("List", anonType))));

            method.Statements.Add(new CodeVariableDeclarationStatement(new CodeTypeReference("IEnumerator", _codeStack.Peek().Scope.CodeDomReference), "o",
                new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("outer"), "GetEnumerator")));

            var outerLoop = new CodeIterationStatement();
            outerLoop.InitStatement = new CodeSnippetStatement();
            outerLoop.IncrementStatement = new CodeSnippetStatement();
            outerLoop.TestExpression = new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("o"), "MoveNext");

            outerLoop.Statements.Add(new CodeVariableDeclarationStatement(_codeStack.Peek().Scope.CodeDomReference, "oc",
                new CodePropertyReferenceExpression(new CodeVariableReferenceExpression("o"), "Current")));

            outerLoop.Statements.Add(new CodeVariableDeclarationStatement(new CodeTypeReference("IEnumerator", fetchAnonType), "i",
                new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("table"), "GetEnumerator")));

            var innerLoop = new CodeIterationStatement();
            outerLoop.Statements.Add(innerLoop);
            innerLoop.InitStatement = new CodeSnippetStatement();
            innerLoop.IncrementStatement = new CodeSnippetStatement();
            innerLoop.TestExpression = new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("i"), "MoveNext");

            innerLoop.Statements.Add(new CodeVariableDeclarationStatement(fetchAnonType, "ic",
                new CodePropertyReferenceExpression(new CodeVariableReferenceExpression("i"), "Current")));

            var booleanArgs = VisitChild(statement.Expression);
            string booleanString = ReplaceBooleanStatement(statement, GenerateCodeFromExpression(booleanArgs.CodeExpression));

            var joinIf = new CodeConditionStatement(new CodeSnippetExpression(booleanString));
            innerLoop.Statements.Add(joinIf);

            joinIf.TrueStatements.Add(new CodeVariableDeclarationStatement(anonType, "t", new CodeObjectCreateExpression(anonType)));

            for(int x = 0; x <_joinMembers.Count - 1; x++)
            {
                joinIf.TrueStatements.Add(new CodeAssignStatement(
                    new CodePropertyReferenceExpression(
                        new CodeVariableReferenceExpression("t"), _joinMembers[x].Name),
                    new CodePropertyReferenceExpression(
                        new CodeVariableReferenceExpression("oc"), _joinMembers[x].Name)));
            }

            joinIf.TrueStatements.Add(new CodeAssignStatement(
                    new CodePropertyReferenceExpression(
                        new CodeVariableReferenceExpression("t"), _joinMembers[_joinMembers.Count-1].Name),
                    new CodePropertyReferenceExpression(
                        new CodeVariableReferenceExpression("ic"), _joinMembers[_joinMembers.Count - 1].Name)));

            joinIf.TrueStatements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("join"), "Add", new CodeVariableReferenceExpression("t")));
            method.Statements.Add(outerLoop);

            if(statement.Join != null)
            {
                var args = VisitChild(statement.Join, new CodeDomArg() { Scope = new ScopeData<Type> { Type = typeof(int), CodeDomReference = anonType } });

                method.Statements.Add(new CodeMethodReturnStatement(args.CodeExpression));
                method.ReturnType = args.Scope.CodeDomReference;
                _codeStack.Peek().Scope = args.Scope;
            }
            else
            {
                var tableType = new CodeTypeReference("CodeTable", anonType);
                method.ReturnType = tableType;
                _codeStack.Peek().Scope = new ScopeData<Type> { Type = typeof(int), CodeDomReference = tableType };

                method.Statements.Add(new CodeVariableDeclarationStatement(tableType, "newTable",
                    new CodeObjectCreateExpression(tableType)));

                method.Statements.Add(new CodeMethodInvokeExpression(
                    new CodeVariableReferenceExpression("newTable"), "SetRows",
                    new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("join"), "ToList")));

                method.Statements.Add(new CodeMethodReturnStatement(new CodeVariableReferenceExpression("newTable")));
            }

            _codeStack.Peek().CodeExpression = new CodeMethodInvokeExpression(
               new CodeMethodReferenceExpression(null, method.Name), new CodeVariableReferenceExpression("join"));
        }