// Path: src/main/java/yk/senjin/shaders/gshader/ShaderTranslator.java
// public static boolean isPrimitive(String oglType) {
//     return PRIMITIVES.contains(oglType);
// }
// 
// Path: src/main/java/yk/senjin/shaders/gshader/ShaderTranslator.java
// public static String translateType(String groovyType) {
//     String t = al(groovyType.split("\\.")).last();
//     if (!convertions.containsKey(t)) return groovyType;
//     return convertions.get(t);
// }


import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.FieldNode;
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.Parameter;
import org.codehaus.groovy.ast.builder.AstBuilder;
import org.codehaus.groovy.ast.expr.*;
import org.codehaus.groovy.ast.stmt.BlockStatement;
import org.codehaus.groovy.ast.stmt.ExpressionStatement;
import org.codehaus.groovy.ast.stmt.IfStatement;
import org.codehaus.groovy.ast.stmt.ReturnStatement;
import org.codehaus.groovy.control.CompilePhase;
import org.junit.Test;
import yk.jcommon.collections.*;
import yk.jcommon.match2.*;
import yk.jcommon.probe.Probe;
import yk.jcommon.probe.State;
import yk.jcommon.search.SSearch;
import yk.jcommon.utils.IO;
import static org.junit.Assert.assertEquals;
import static yk.jcommon.collections.YArrayList.al;
import static yk.jcommon.collections.YHashMap.hm;
import static yk.jcommon.collections.YHashSet.hs;
import static yk.jcommon.match2.MatcherShortNames.*;
import static yk.senjin.shaders.gshader.ShaderTranslator.isPrimitive;
import static yk.senjin.shaders.gshader.ShaderTranslator.translateType;

    public static YHashMap<String, YSet<String>> inferInOutModifiers(Object nodes) {
        YList<Object> accessors = YArrayList.al(new MatchByIndex(new MatchVar("access")));
        YList<Object> accessors2 = accessors.with(MatchProperty.p("methodsList", new MatchVar("access")));
        YSet<YMap<String, Object>> method = new Matcher().match(nodes, new MatchDeeper(accessors2, var("method", p(MethodNode.class, "name", var("methodName")))));
        YHashMap<String, YSet<String>> modifiers = hm();
        int oldModifiersCount = 0;
        while (true) {

            for (YMap<String, Object> m : method) {
//                System.out.println("method: " + m.get("methodName"));
                getArgsModifiers((MethodNode) m.get("method"), modifiers);
//                System.out.println(modifiers);
            }
            int newModifiersCount = modifiers.values().reduce(0, (i, ss) -> i + ss.size());
            if (newModifiersCount == oldModifiersCount) break;
//            System.out.println("AND AGAIN");
            oldModifiersCount = newModifiersCount;
        }
        return modifiers;
    }

    public static YMap<String, YSet<String>> getArgsModifiers(MethodNode methodNode, YMap<String, YSet<String>> result) {

        Object fieldWritePattern = new MatchDeeper(G_BODY_ACCESSORS,
                p(BinaryExpression.class, "operation", p("text", "="),
                        "leftExpression", p(PropertyExpression.class, "objectExpression", p(VariableExpression.class, "variable", var("name")), "property", p("value", var("value")))
                ));

        YSet<YMap<String, Object>> paramMm = new Matcher().match(methodNode, p("parameters", i(var("paramIndex"), p("name", var("paramName")))));
// Path: src/main/java/yk/senjin/shaders/gshader/ShaderTranslator.java
// public static boolean isPrimitive(String oglType) {
//     return PRIMITIVES.contains(oglType);
// }
// 
// Path: src/main/java/yk/senjin/shaders/gshader/ShaderTranslator.java
// public static String translateType(String groovyType) {
//     String t = al(groovyType.split("\\.")).last();
//     if (!convertions.containsKey(t)) return groovyType;
//     return convertions.get(t);
// }


// Path: src/main/java/yk/senjin/shaders/gshader/analysis/GglslAnalyzer.java
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.FieldNode;
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.Parameter;
import org.codehaus.groovy.ast.builder.AstBuilder;
import org.codehaus.groovy.ast.expr.*;
import org.codehaus.groovy.ast.stmt.BlockStatement;
import org.codehaus.groovy.ast.stmt.ExpressionStatement;
import org.codehaus.groovy.ast.stmt.IfStatement;
import org.codehaus.groovy.ast.stmt.ReturnStatement;
import org.codehaus.groovy.control.CompilePhase;
import org.junit.Test;
import yk.jcommon.collections.*;
import yk.jcommon.match2.*;
import yk.jcommon.probe.Probe;
import yk.jcommon.probe.State;
import yk.jcommon.search.SSearch;
import yk.jcommon.utils.IO;
import static org.junit.Assert.assertEquals;
import static yk.jcommon.collections.YArrayList.al;
import static yk.jcommon.collections.YHashMap.hm;
import static yk.jcommon.collections.YHashSet.hs;
import static yk.jcommon.match2.MatcherShortNames.*;
import static yk.senjin.shaders.gshader.ShaderTranslator.isPrimitive;
import static yk.senjin.shaders.gshader.ShaderTranslator.translateType;


    public static YHashMap<String, YSet<String>> inferInOutModifiers(Object nodes) {
        YList<Object> accessors = YArrayList.al(new MatchByIndex(new MatchVar("access")));
        YList<Object> accessors2 = accessors.with(MatchProperty.p("methodsList", new MatchVar("access")));
        YSet<YMap<String, Object>> method = new Matcher().match(nodes, new MatchDeeper(accessors2, var("method", p(MethodNode.class, "name", var("methodName")))));
        YHashMap<String, YSet<String>> modifiers = hm();
        int oldModifiersCount = 0;
        while (true) {

            for (YMap<String, Object> m : method) {
//                System.out.println("method: " + m.get("methodName"));
                getArgsModifiers((MethodNode) m.get("method"), modifiers);
//                System.out.println(modifiers);
            }
            int newModifiersCount = modifiers.values().reduce(0, (i, ss) -> i + ss.size());
            if (newModifiersCount == oldModifiersCount) break;
//            System.out.println("AND AGAIN");
            oldModifiersCount = newModifiersCount;
        }
        return modifiers;
    }

    public static YMap<String, YSet<String>> getArgsModifiers(MethodNode methodNode, YMap<String, YSet<String>> result) {

        Object fieldWritePattern = new MatchDeeper(G_BODY_ACCESSORS,
                p(BinaryExpression.class, "operation", p("text", "="),
                        "leftExpression", p(PropertyExpression.class, "objectExpression", p(VariableExpression.class, "variable", var("name")), "property", p("value", var("value")))
                ));

        YSet<YMap<String, Object>> paramMm = new Matcher().match(methodNode, p("parameters", i(var("paramIndex"), p("name", var("paramName")))));
        for (YMap<String, Object> paramM : paramMm) if (!isPrimitive(translateType((String) paramM.get("paramName")))) {