Example #1
0
        static bool AddVisitCode(EasyMethod m, FieldInfo field, CodeExpression var, List <CodeStatement> assertions, bool transformer)
        {
            CodeExpression prop      = var.Property(GetPropertyName(field.Name));
            CodeExpression nodeStack = Easy.Var("nodeStack");

            if (field.FieldType.FullName.StartsWith("System.Collections.Generic.List"))
            {
                Type elType = field.FieldType.GetGenericArguments()[0];
                if (!typeof(INode).IsAssignableFrom(elType))
                {
                    return(false);
                }
                assertions.Add(IfNullSetFailure(prop));
                string code;
                string propertyName = GetCode(prop);
                if (transformer)
                {
                    code = CreateTransformerLoop(propertyName, ConvertType(elType).BaseType);
                }
                else
                {
                    code =
                        "\t\t\tif (" + propertyName + ".Count == data." + GetPropertyName(field.Name) + ".Count) {\n" +
                        "\t\t\tfor (int i=0; i<" + propertyName + ".Count;i++) {\n" +
                        "\t\t\t\t" + ConvertType(elType).BaseType + " o = " + propertyName + "[i];\n" +
                        "\t\t\t\tif(o == null){return SetFailure();}\n" + "\t\t\t\tif((bool)o.AcceptVisitor(this, data." + GetPropertyName(field.Name) + "[i]) == false) return SetFailure();\n" +
                        "\t\t\t}" +
                        "\t\t\t}" +
                        "\t\t\telse { return SetFailure(); }";
                }
                m.Statements.Add(new CodeSnippetStatement(code));
                return(true);
            }
            if (!typeof(INode).IsAssignableFrom(field.FieldType))
            {
                return(false);
            }
            assertions.Add(IfNullSetFailure(prop));
            if (transformer)
            {
                m.Statements.Add(nodeStack.InvokeMethod("Push", prop));
            }
            m.Statements.Add(prop.InvokeMethod("AcceptVisitor",
                                               Easy.This,
                                               Easy.Var("data." + var.Property(GetPropertyName(field.Name)).PropertyName)));
            if (transformer)
            {
                m.Body.Assign(prop, nodeStack.InvokeMethod("Pop").CastTo(ConvertType(field.FieldType)));
            }
            return(true);
        }
Example #2
0
        static bool AddVisitCode(EasyMethod m, FieldInfo field, CodeExpression var, List <CodeStatement> assertions, bool transformer)
        {
            CodeExpression prop      = var.Property(GetPropertyName(field.Name));
            CodeExpression nodeStack = Easy.Var("nodeStack");

            if (field.FieldType.FullName.StartsWith("System.Collections.Generic.List"))
            {
                Type elType = field.FieldType.GetGenericArguments()[0];
                if (!typeof(INode).IsAssignableFrom(elType))
                {
                    return(false);
                }
                assertions.Add(AssertIsNotNull(prop));
                string code;
                if (transformer)
                {
                    code = CreateTransformerLoop(GetCode(prop), ConvertType(elType).BaseType);
                }
                else
                {
                    code =
                        "\t\t\tforeach (" + ConvertType(elType).BaseType + " o in " + GetCode(prop) + ") {\n" +
                        "\t\t\t\tDebug.Assert(o != null);\n" +
                        "\t\t\t\to.AcceptVisitor(this, data);\n" +
                        "\t\t\t}";
                }
                m.Statements.Add(new CodeSnippetStatement(code));
                return(true);
            }
            if (!typeof(INode).IsAssignableFrom(field.FieldType))
            {
                return(false);
            }
            assertions.Add(AssertIsNotNull(prop));
            if (transformer)
            {
                m.Statements.Add(nodeStack.InvokeMethod("Push", prop));
            }
            m.Statements.Add(prop.InvokeMethod("AcceptVisitor",
                                               Easy.This,
                                               Easy.Var("data")));
            if (transformer)
            {
                m.Body.Assign(prop, nodeStack.InvokeMethod("Pop").CastTo(ConvertType(field.FieldType)));
            }
            return(true);
        }
Example #3
0
        static CodeTypeDeclaration CreateAstVisitorClass(List <Type> nodeTypes, bool transformer)
        {
            CodeTypeDeclaration td = new CodeTypeDeclaration(transformer ? "AbstractAstTransformer" : "AbstractAstVisitor");

            td.TypeAttributes = TypeAttributes.Public | TypeAttributes.Abstract;
            td.BaseTypes.Add(new CodeTypeReference("IAstVisitor"));

            if (transformer)
            {
                string comment =
                    "The AbstractAstTransformer will iterate through the whole AST,\n " +
                    "just like the AbstractAstVisitor. However, the AbstractAstTransformer allows\n " +
                    "you to modify the AST at the same time: It does not use 'foreach' internally,\n " +
                    "so you can add members to collections of parents of the current node (but\n " +
                    "you cannot insert or delete items as that will make the index used invalid).\n " +
                    "You can use the methods ReplaceCurrentNode and RemoveCurrentNode to replace\n " +
                    "or remove the current node, totally independent from the type of the parent node.";
                Easy.AddSummary(td, comment);

                CodeMemberField field = td.AddField(Easy.TypeRef("Stack", "INode"), "nodeStack");
                field.InitExpression = Easy.New(field.Type);

                /*
                 * CodeExpression nodeStack = Easy.Var("nodeStack");
                 * CodeMemberProperty p = new CodeMemberProperty();
                 * p.Name = "CurrentNode";
                 * p.Type = new CodeTypeReference("INode");
                 * p.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                 * p.GetStatements.Add(new CodeMethodReturnStatement(new CodeVariableReferenceExpression("currentNode")));
                 * p.SetStatements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("currentNode"),
                 *                                          new CodePropertySetValueReferenceExpression()));
                 * td.Members.Add(p);
                 */

                EasyMethod m = td.AddMethod("ReplaceCurrentNode");
                m.AddParameter(Easy.TypeRef("INode"), "newNode");
                m.Statements.Add(Easy.Var("nodeStack").InvokeMethod("Pop"));
                m.Statements.Add(Easy.Var("nodeStack").InvokeMethod("Push", Easy.Var("newNode")));

                m = td.AddMethod("RemoveCurrentNode");
                m.Statements.Add(Easy.Var("nodeStack").InvokeMethod("Pop"));
                m.Statements.Add(Easy.Var("nodeStack").InvokeMethod("Push", Easy.Null));
            }

            foreach (Type type in nodeTypes)
            {
                if (!type.IsAbstract)
                {
                    EasyMethod m = td.AddMethod(typeof(object), VisitPrefix + type.Name);
                    m.Attributes = MemberAttributes.Public;
                    m.AddParameter(ConvertType(type), GetFieldName(type.Name));
                    m.AddParameter(typeof(object), "data");

                    List <CodeStatement> assertions = new List <CodeStatement>();
                    string         varVariableName  = GetFieldName(type.Name);
                    CodeExpression var = Easy.Var(varVariableName);
                    assertions.Add(AssertIsNotNull(var));

                    AddFieldVisitCode(m, type, var, assertions, transformer);

                    if (type.GetCustomAttributes(typeof(HasChildrenAttribute), true).Length > 0)
                    {
                        if (transformer)
                        {
                            m.Statements.Add(new CodeSnippetStatement(CreateTransformerLoop(varVariableName + ".Children", "INode")));
                            m.Body.Return(Easy.Null);
                        }
                        else
                        {
                            m.Body.Return(var.InvokeMethod("AcceptChildren", Easy.This, Easy.Var("data")));
                        }
                    }
                    else
                    {
                        CodeExpressionStatement lastStatement = null;
                        if (m.Statements.Count > 0)
                        {
                            lastStatement = m.Statements[m.Statements.Count - 1] as CodeExpressionStatement;
                        }
                        if (lastStatement != null)
                        {
                            m.Statements.RemoveAt(m.Statements.Count - 1);
                            m.Body.Return(lastStatement.Expression);
                        }
                        else
                        {
                            m.Body.Return(Easy.Null);
                        }
                    }

                    for (int i = 0; i < assertions.Count; i++)
                    {
                        m.Statements.Insert(i, assertions[i]);
                    }
                }
            }
            return(td);
        }
Example #4
0
        static CodeTypeDeclaration CreateAstComparisonVisitorClass(List <Type> nodeTypes)
        {
            CodeTypeDeclaration td = new CodeTypeDeclaration("AstComparisonVisitor");

            td.TypeAttributes = TypeAttributes.Public;
            td.IsPartial      = true;

            //td.BaseTypes.Add(new CodeTypeReference("IAstVisitor"));

            foreach (Type type in nodeTypes)
            {
                if (!type.IsAbstract)
                {
                    EasyMethod m = td.AddMethod(typeof(bool), VisitPrefix + type.Name);
                    m.Attributes = MemberAttributes.Public;
                    m.AddParameter(ConvertType(type), GetFieldName(type.Name));
                    const string right_hand_side_name = "d";
                    m.AddParameter(typeof(object), right_hand_side_name);

                    List <CodeStatement> assertions = new List <CodeStatement>();
                    string         varVariableName  = GetFieldName(type.Name);
                    CodeExpression var = Easy.Var(varVariableName);
                    assertions.Add(IfNullSetFailure(var));

                    if (varVariableName == "using")
                    {
                        varVariableName = "@using";
                    }

                    CodeExpression r_var = Easy.Var(right_hand_side_name);
                    assertions.Add(IfNullSetFailure(r_var));

                    // Confirm their types are the same.
                    m.Statements.Add(new CodeSnippetStatement("\t\t\tif(" + varVariableName + ".GetType() != " + right_hand_side_name + ".GetType()) {return SetFailure();}"));

                    // Cast the object parameter to whatever the other parameter is, and call the variable 'data'.
                    // Like so: AddHandlerStatement data = (AddHandlerStatement) d;
                    m.Statements.Add(new CodeSnippetStatement("\t\t\tvar data = (" + ConvertType(type).BaseType + ")d;"));

                    m.Statements.Add(new CodeConditionStatement(new CodeSnippetExpression("!IsMatch(" + varVariableName + ", data)"),
                                                                new CodeSnippetStatement("\t\t\t\treturn SetFailure();")));

                    AddFieldVisitCode(m, type, var, assertions, false);

                    if (type.GetCustomAttributes(typeof(HasChildrenAttribute), true).Length > 0)
                    {
                        m.Body.Return(var.InvokeMethod("AcceptChildren", Easy.This, Easy.Var(right_hand_side_name)));
                    }
                    else
                    {
                        CodeExpressionStatement lastStatement = null;
                        if (m.Statements.Count > 0)
                        {
                            lastStatement = m.Statements[m.Statements.Count - 1] as CodeExpressionStatement;
                        }
                        if (lastStatement != null)
                        {
                            m.Statements.RemoveAt(m.Statements.Count - 1);
                            m.Body.Return(lastStatement.Expression);
                        }
                        else
                        {
                            m.Body.Return(new CodeSnippetExpression("true"));
                        }
                    }

                    for (int i = 0; i < assertions.Count; i++)
                    {
                        m.Statements.Insert(i, assertions[i]);
                    }
                }
            }
            return(td);
        }