summaryrefslogblamecommitdiffstats
path: root/src/draw.c
blob: a89f9079a223bd361c103ddd5e2caed47396f87a (plain) (tree)
1
2
3
4
5
6
7
8


                    
 
                 
 

                    




                   































                                                               
                                                         
 
                                    












             
                                   



            

                                    

                                        
                                 
                                             

                                               

                                                 
                                          

                                             
                                              

                                                 
                                                        

                                                           

                                  

                  
                               
                                            


                                                       

                                             
                                         

                                            
                                             

                                                

                                  
             
                                                     
                  
                                       

                                           
                                

                                    
                                  

                                      
                                               

                                                   
                                      

                                          
                                 
                                      

                                               

                                              
                                         

                                            
                                            

                                               
                                        

                                           
                                                   
                                                      
                                                             
                          
                                            

                                               

                                  

                  
                                 
                                      


                                                                                     
                          

                                                                                   
                          

                                  
             
                                                     
                  
                                        
                                             


                                                                      
                          

                                                                        
                          

                                                                                 
                          
                                            

                                  
             
                                                     
                  
                                                      

                                                          
                                                     







                                                                                  

                                           
                                                           
 
                     
                     

                                 
                                                        

                               
 



                                                                                       

     
                 

 
                                                               
 

                                  

                                           
                        
 
 




















                                                             




                                                             
                             
     


                                              

                                  




































                                                                        
                               
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "draw.h"

#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>


static void print_ast_value(FILE *fp, CcmmcAstValueType type) {
    putc(' ', fp);
    switch (type) {
        case CCMMC_AST_VALUE_INT:
            fprintf(fp, "<int>");
            break;
        case CCMMC_AST_VALUE_FLOAT:
            fprintf(fp, "<float>");
            break;
        case CCMMC_AST_VALUE_VOID:
            fprintf(fp, "<void>");
            break;
        case CCMMC_AST_VALUE_INT_PTR:
            fprintf(fp, "<int*>");
            break;
        case CCMMC_AST_VALUE_FLOAT_PTR:
            fprintf(fp, "<float*>");
            break;
        case CCMMC_AST_VALUE_CONST_STRING:
            fprintf(fp, "<const char*>");
            break;
        case CCMMC_AST_VALUE_NONE:
            fprintf(fp, "<none>");
            break;
        case CCMMC_AST_VALUE_ERROR:
            fprintf(fp, "<error>");
            break;
        default:
            assert(false);
    }
}

static void printLabelString(FILE *fp, CcmmcAst *astNode)
{
    const char *binaryOpString[] = {
        "+",
        "-",
        "*",
        "/",
        "==",
        ">=",
        "<=",
        "!=",
        ">",
        "<",
        "&&",
        "||"
    };
    const char *unaryOpString[] = {
        "+",
        "-",
        "!"
    };
    switch (astNode->type_node) {
        case CCMMC_AST_NODE_PROGRAM:
            fprintf(fp, "PROGRAM_NODE");
            break;
        case CCMMC_AST_NODE_DECL:
            fprintf(fp, "DECLARATION_NODE ");
            switch (astNode->value_decl.kind) {
                case CCMMC_KIND_DECL_VARIABLE:
                    fprintf(fp, "VARIABLE_DECL");
                    break;
                case CCMMC_KIND_DECL_TYPE:
                    fprintf(fp, "TYPE_DECL");
                    break;
                case CCMMC_KIND_DECL_FUNCTION:
                    fprintf(fp, "FUNCTION_DECL");
                    break;
                case CCMMC_KIND_DECL_FUNCTION_PARAMETER:
                    fprintf(fp, "FUNCTION_PARAMETER_DECL");
                    break;
                default:
                    assert(false);
            }
            break;
        case CCMMC_AST_NODE_ID:
            fprintf(fp, "IDENTIFIER_NODE ");
            fprintf(fp, "%s ", astNode->value_id.name);
            switch (astNode->value_id.kind) {
                case CCMMC_KIND_ID_NORMAL:
                    fprintf(fp, "NORMAL_ID");
                    break;
                case CCMMC_KIND_ID_ARRAY:
                    fprintf(fp, "ARRAY_ID");
                    break;
                case CCMMC_KIND_ID_WITH_INIT:
                    fprintf(fp, "WITH_INIT_ID");
                    break;
                default:
                    assert(false);
            }
            print_ast_value(fp, astNode->type_value);
            break;
        case CCMMC_AST_NODE_PARAM_LIST:
            fprintf(fp, "PARAM_LIST_NODE");
            break;
        case CCMMC_AST_NODE_NUL:
            fprintf(fp, "NUL_NODE");
            break;
        case CCMMC_AST_NODE_BLOCK:
            fprintf(fp, "BLOCK_NODE");
            break;
        case CCMMC_AST_NODE_VARIABLE_DECL_LIST:
            fprintf(fp, "VARIABLE_DECL_LIST_NODE");
            break;
        case CCMMC_AST_NODE_STMT_LIST:
            fprintf(fp, "STMT_LIST_NODE");
            break;
        case CCMMC_AST_NODE_STMT:
            fprintf(fp, "STMT_NODE ");
            switch (astNode->value_stmt.kind) {
                case CCMMC_KIND_STMT_WHILE:
                    fprintf(fp, "WHILE_STMT");
                    break;
                case CCMMC_KIND_STMT_FOR:
                    fprintf(fp, "FOR_STMT");
                    break;
                case CCMMC_KIND_STMT_ASSIGN:
                    fprintf(fp, "ASSIGN_STMT");
                    break;
                case CCMMC_KIND_STMT_IF:
                    fprintf(fp, "IF_STMT");
                    break;
                case CCMMC_KIND_STMT_FUNCTION_CALL:
                    fprintf(fp, "FUNCTION_CALL_STMT");
                    print_ast_value(fp, astNode->type_value);
                    break;
                case CCMMC_KIND_STMT_RETURN:
                    fprintf(fp, "RETURN_STMT");
                    break;
                default:
                    assert(false);
            }
            break;
        case CCMMC_AST_NODE_EXPR:
            fprintf(fp, "EXPR_NODE ");
            switch (astNode->value_expr.kind) {
                case CCMMC_KIND_EXPR_BINARY_OP:
                    fprintf(fp, "%s", binaryOpString[astNode->value_expr.op_binary]);
                    break;
                case CCMMC_KIND_EXPR_UNARY_OP:
                    fprintf(fp, "%s", unaryOpString[astNode->value_expr.op_unary]);
                    break;
                default:
                    assert(false);
            }
            print_ast_value(fp, astNode->type_value);
            break;
        case CCMMC_AST_NODE_CONST_VALUE:
            fprintf(fp, "CONST_VALUE_NODE ");
            switch (astNode->value_const.kind) {
                case CCMMC_KIND_CONST_INT:
                    fprintf(fp, "%d", astNode->value_const.const_int);
                    break;
                case CCMMC_KIND_CONST_FLOAT:
                    fprintf(fp, "%f", astNode->value_const.const_float);
                    break;
                case CCMMC_KIND_CONST_STRING:
                    fprintf(fp, "\\\"%s\\\"", astNode->value_const.const_string);
                    break;
                case CCMMC_KIND_CONST_ERROR:
                default:
                    assert(false);
            }
            print_ast_value(fp, astNode->type_value);
            break;
        case CCMMC_AST_NODE_NONEMPTY_ASSIGN_EXPR_LIST:
            fprintf(fp, "NONEMPTY_ASSIGN_EXPR_LIST_NODE");
            break;
        case CCMMC_AST_NODE_NONEMPTY_RELOP_EXPR_LIST:
            fprintf(fp, "NONEMPTY_RELOP_EXPR_LIST_NODE");
            break;
        default:
            fprintf(fp, "default case in char *getLabelString(AST_TYPE astType)");
            break;
    }
}

// count: the (unused) id number to be used
// return: then next unused id number
static int printGVNode(FILE *fp, CcmmcAst *node, int count)
{
    if (node == NULL)
        return count;

    int currentNodeCount = count;
    fprintf(fp, "node%d [shape=box] [label =\"", count);
    printLabelString(fp, node);
    fprintf(fp, "\"]\n");

    for (CcmmcAst *child = node->child; child != NULL; child = child->right_sibling) {
        int this_count = count + 1;
        count = printGVNode(fp, child, this_count);
        fprintf(fp, "node%d -> node%d [style = bold]\n", currentNodeCount, this_count);
    }

    return count;
}

void ccmmc_draw_ast(FILE *fp, const char *name, CcmmcAst *root)
{
    fprintf(fp , "Digraph AST\n");
    fprintf(fp , "{\n");
    fprintf(fp , "label = \"%s\"\n", name);
    printGVNode(fp, root, 0);
    fprintf(fp , "}\n");
}

static void print_symbol_type(FILE *fp, CcmmcSymbolType type)
{
    switch (type.type_base) {
        case CCMMC_AST_VALUE_INT:
            fputs("int", fp);
            break;
        case CCMMC_AST_VALUE_FLOAT:
            fputs("float", fp);
            break;
        case CCMMC_AST_VALUE_VOID:
            fputs("void", fp);
            break;
        case CCMMC_AST_VALUE_INT_PTR:
        case CCMMC_AST_VALUE_FLOAT_PTR:
        case CCMMC_AST_VALUE_CONST_STRING:
        case CCMMC_AST_VALUE_NONE:
        case CCMMC_AST_VALUE_ERROR:
        default:
            assert(false);
    }

    if (ccmmc_symbol_type_is_array(type)) {
        if (type.array_size != NULL)
            for (size_t i = 0; i < type.array_dimension; i++)
                fprintf(fp, "[%zu]", type.array_size[i]);
        else
            fprintf(fp, "*");
    }

    if (ccmmc_symbol_type_is_function(type)) {
        fputs(" (*)(", fp);
        if (type.param_count == 0)
            fputs("void)", fp);
        for (size_t i = 0; i < type.param_count; i++) {
            print_symbol_type(fp, type.param_list[i]);
            if (i == type.param_count - 1)
                fputs(")", fp);
            else
                fputs(", ", fp);
        }
    }
}

void ccmmc_draw_symbol_scope(FILE *fp, CcmmcSymbolScope *scope)
{
    for (int i = 0; i < CCMMC_SYMBOL_SCOPE_HASH_TABLE_SIZE; i++) {
        for (CcmmcSymbol *symbol = scope->hash_table[i]; symbol != NULL;
             symbol = symbol->next) {
            fprintf(fp, "Bucket %d: %s, ", i, symbol->name);
            switch (symbol->kind) {
                case CCMMC_SYMBOL_KIND_TYPE:
                    fputs("TYPE, ", fp);
                    print_symbol_type(fp, symbol->type);
                    break;
                case CCMMC_SYMBOL_KIND_VARIABLE:
                    fputs("VARIABLE, ", fp);
                    print_symbol_type(fp, symbol->type);
                    break;
                case CCMMC_SYMBOL_KIND_FUNCTION:
                    fputs("FUNCTION, ", fp);
                    print_symbol_type(fp, symbol->type);
                    break;
                default:
                    assert(false);
            }
            putc('\n', fp);
        }
    }
}

// vim: set sw=4 ts=4 sts=4 et: