haxiomic / haxe-glsl-parser

GLSL ES 1.0 parser in Haxe
MIT License
26 stars 7 forks source link

AST Nodes doesn't work from a build macro #9

Closed deanm closed 7 years ago

deanm commented 7 years ago

The nodes of SyntaxTree are built up using NodeBuildMacro. I am trying to use the parser from a build macro, which means this doesn't work. It's fine if it's less convenient, I'm just trying to understand how I can walk through the AST anyway (obviously the underlying structure is there somehow), any advice?

haxiomic commented 7 years ago

The build macro just sets the nodeName and nodeType fields based on the class name, it was helpful while developing but now SyntaxTree isn't changing it doesn't need to exist. It was a bit of an oversight on my part to not think about macro use

I'll update it with the nodeType values baked in and remove the nodeName field since it's not that useful

As for walking the AST, here's some sample code that prints function declarations

import glsl.lex.Tokenizer;
import glsl.preprocess.Preprocessor;
import glsl.parse.Parser;
import glsl.SyntaxTree;
import glsl.SyntaxTree.Node;

//adds .print() to each node
using glsl.print.SyntaxPrinter;

class Main{

    static function main(){
        var fragmentShader = '
            #define TEST 0.0
            uniform vec2 position;

            //prototype
            int someFunction(in float x, out float result);

            void main(){
                gl_FragColor = vec4(cos(position), TEST, 1.0);
            }

            int someFunction(in float x, out float result){
                result = x*2.0;
                return x;
            }
        ';

        //parsing example
        var tokens = Tokenizer.tokenize(fragmentShader);

        //uncomment to evaluate preprocessor expressions (at least the ones that can be safely evaluated before runtime)
        // tokens = Preprocessor.process(tokens);

        var ast:Node = Parser.parseTokens(tokens);

        //find all functions
        switch ast.nodeType {
            case RootNode(root):
                for(decl in root.declarations){
                    switch decl.nodeType {
                        case NodeType.FunctionDefinitionNode(definition):
                            trace(
                                'function "' + definition.header.name + '" ' +
                                'returns '+definition.header.returnType.print(null) //convert returnType node into glsl to print as string
                            );
                        default:
                    }

                }
            default:
        }

        //converts any glsl node into a string, pass null for no-whitespace
        trace(ast.print('\t'));
    }

}

I've got a bunch of helper functions for iterating nodes and walking the AST + some basic DCE but it's on my work computer so I'll add those on Monday.

I think the design of SyntaxTree could be improved to make walking easier, it'd be better to base it around the design of haxe.macro.Expr

haxiomic commented 7 years ago

I've removed the macro from SyntaxTree, you should now be able to use it in macros

deanm commented 7 years ago

Yes, now it works great, thanks!