// File: /workspace/github_c_makefile_star2_O0/gregtour[P]minimal-compiler/preprocess.c
// Function: FirstPassStaticAnalyzer
void FirstPassStaticAnalyzer(PROGRAM* root)
{
    GSTMT_LIST* iterator;

    Assert(root != NULL);
    Assert(root->token == SYMBOL_PROGRAM);
    Assert(root->production == PROD_PROGRAM_GSTMT_STAR);
    Assert(root->numChildren == 1);

    // Analyze all top-level declarations of functions and variables
    iterator = root->children[0];

    // Iterate through the list of <gstmt>'s.
    while (iterator && iterator->production == PROD_GSTMT_STAR_GSTMT)
    {
        GSTMT* statement;

        Assert(iterator->token == SYMBOL_GSTMT_STAR);
        Assert(iterator->numChildren == 2);

        statement = (GSTMT*)iterator->children[0];

        Assert(statement != NULL);
        Assert(statement->token == SYMBOL_GSTMT);

        // Link definitions of top level statements
        switch (statement->production)
        {
        case PROD_GSTMT_INCLUDE:
            {
            SYNTAX_TREE* list = statement->children[1];
            // <gstmt> ::= include <string-list> ;
            while (list)
            {
                SYNTAX_TREE* string = list->children[0];
                const char* sourcefile = string->string;

                Assert(list->token == SYMBOL_STRING_LIST);
                Assert(string && string->token == gSymbolString);

                LinkSourceRoot(sourcefile, &statement);

                if (list->numChildren > 1) 
                {
                    // <string-list> ::= <string> , <string-list>
                    Assert(list->numChildren == 3);
                    list = list->children[2];
                } 
                else 
                {
                    // <string-list> ::= <string>
                    list = NULL;
                }
            }

            break;
            }
        case PROD_GSTMT_TYPE_DECLARATION:
            {
            // <gstmt> ::= <type-declaration> ;
            SYNTAX_TREE* declaration = statement->children[0];
            TYPE_DECL* typeTag;
            TYPE type;
            Assert(declaration->token == SYMBOL_TYPE_DECLARATION);

            // (A) <type-declaration> ::= <identifier> : <type>
            // (B) <type-declaration> ::= <identifier> , <type-declaration>
            typeTag = (TYPE_DECL*)declaration->children[2];

            while (typeTag->token != SYMBOL_TYPE) 
            {
                Assert(typeTag->token == SYMBOL_TYPE_DECLARATION);
                Assert(typeTag->numChildren == 3);
                typeTag = typeTag->children[2];
            }

            type = DeriveType(typeTag);
            // LinkVariable(<type>, <identifier>)
            while (declaration->token == SYMBOL_TYPE_DECLARATION)
            {
                const char* identifier = declaration->children[0]->string;
                LinkVariableRoot(type, identifier);

                declaration = declaration->children[2];
            }

            break;
            }
        case PROD_GSTMT_IDENTIFIER_A:
            {
            const char* funcName;
            TYPE returnType;
            SYNTAX_TREE* code;
            Assert(statement->numChildren == 4);

            // <gstmt> ::= <identifier> : <type> <block>
            funcName = statement->children[0]->string;
            returnType = DeriveType(statement->children[2]);
            code = statement->children[3];

            // parameterless function method
            LinkFunctionRoot(returnType, funcName, NULL, code);
            break;
            }
        case PROD_GSTMT_IDENTIFIER_B:
            {
            const char* funcName; 
            SYNTAX_TREE* params;
            TYPE returnType;
            SYNTAX_TREE* code;

            Assert(statement->numChildren == 7);

            // <gstmt> ::= <identifier> ( <param*> ) : <type> <block>
            funcName = statement->children[0]->string;
            params = statement->children[2];
            returnType = DeriveType(statement->children[5]);
            code = statement->children[6];

            // function method
            LinkFunctionRoot(returnType, funcName, params, code);

            break;
            }
        default:
            AssertS(0, "Unrecognized instruction encountered.");
            CompilerError("Unknown instruction.");
            break;
        }

        // process the next statement
        iterator = iterator->children[1];
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rax
movq (%rax), %rax
movq %rax, -0x10(%rbp)
xorl %eax, %eax
cmpq $0x0, -0x10(%rbp)
movb %al, -0xa1(%rbp)
je 0x881e
movq -0x10(%rbp), %rax
cmpl $0x2, 0x4(%rax)
sete %al
movb %al, -0xa1(%rbp)
movb -0xa1(%rbp), %al
testb $0x1, %al
jne 0x882d
jmp 0x8a74
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq (%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movl 0x4(%rax), %eax
addl $-0x4, %eax
movl %eax, %ecx
movq %rcx, -0xb0(%rbp)
subl $0x7, %eax
ja 0x8a47
movq -0xb0(%rbp), %rax
leaq 0x2f82(%rip), %rcx      # 0xb7e8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x18(%rbp), %rax
movq 0x28(%rax), %rax
movq 0x8(%rax), %rax
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x20(%rbp)
je 0x88d4
movq -0x20(%rbp), %rax
movq 0x28(%rax), %rax
movq (%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rdi
leaq -0x18(%rbp), %rsi
callq 0x9990
movq -0x20(%rbp), %rax
cmpl $0x1, 0x20(%rax)
jle 0x88ca
movq -0x20(%rbp), %rax
movq 0x28(%rax), %rax
movq 0x10(%rax), %rax
movq %rax, -0x20(%rbp)
jmp 0x88d2
movq $0x0, -0x20(%rbp)
jmp 0x887f
jmp 0x8a5f
movq -0x18(%rbp), %rax
movq 0x28(%rax), %rax
movq (%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
movq 0x28(%rax), %rax
movq 0x10(%rax), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
cmpl $0x1006, (%rax)         # imm = 0x1006
je 0x8916
movq -0x40(%rbp), %rax
movq 0x28(%rax), %rax
movq 0x10(%rax), %rax
movq %rax, -0x40(%rbp)
jmp 0x88f8
movq -0x40(%rbp), %rdi
callq 0x98e0
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x38(%rbp), %rax
cmpl $0x1005, (%rax)         # imm = 0x1005
jne 0x8969
movq -0x38(%rbp), %rax
movq 0x28(%rax), %rax
movq (%rax), %rax
movq 0x8(%rax), %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rsi
movq -0x48(%rbp), %rdi
callq 0x9900
movq -0x38(%rbp), %rax
movq 0x28(%rax), %rax
movq 0x10(%rax), %rax
movq %rax, -0x38(%rbp)
jmp 0x892b
jmp 0x8a5f
movq -0x18(%rbp), %rax
movq 0x28(%rax), %rax
movq (%rax), %rax
movq 0x8(%rax), %rax
movq %rax, -0x60(%rbp)
movq -0x18(%rbp), %rax
movq 0x28(%rax), %rax
movq 0x10(%rax), %rdi
callq 0x98e0
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0x18(%rbp), %rax
movq 0x28(%rax), %rax
movq 0x18(%rax), %rax
movq %rax, -0x70(%rbp)
movq -0x60(%rbp), %rsi
movq -0x70(%rbp), %rcx
movq -0x68(%rbp), %rdi
xorl %eax, %eax
movl %eax, %edx
callq 0x97a0
jmp 0x8a5f
movq -0x18(%rbp), %rax
movq 0x28(%rax), %rax
movq (%rax), %rax
movq 0x8(%rax), %rax
movq %rax, -0x80(%rbp)
movq -0x18(%rbp), %rax
movq 0x28(%rax), %rax
movq 0x10(%rax), %rax
movq %rax, -0x88(%rbp)
movq -0x18(%rbp), %rax
movq 0x28(%rax), %rax
movq 0x28(%rax), %rdi
callq 0x98e0
movq %rax, -0xa0(%rbp)
movq -0xa0(%rbp), %rax
movq %rax, -0x90(%rbp)
movq -0x18(%rbp), %rax
movq 0x28(%rax), %rax
movq 0x30(%rax), %rax
movq %rax, -0x98(%rbp)
movq -0x80(%rbp), %rsi
movq -0x88(%rbp), %rdx
movq -0x98(%rbp), %rcx
movq -0x90(%rbp), %rdi
callq 0x97a0
jmp 0x8a5f
leaq 0x2dba(%rip), %rdi      # 0xb808
leaq 0x2dc8(%rip), %rsi      # 0xb81d
movl $0x9b, %edx
callq 0x6e20
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq 0x8(%rax), %rax
movq %rax, -0x10(%rbp)
jmp 0x87fe
addq $0xb0, %rsp
popq %rbp
retq
nopl (%rax)