diff --git a/src/ast/ast.c b/src/ast/ast.c index 6e4c106..93420cb 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -30,6 +30,7 @@ void AST_init() { INFO("filling lookup table..."); + lookup_table[AST_Stmt] = "stmt"; lookup_table[AST_Expr] = "expr"; lookup_table[AST_Add] = "+"; @@ -63,6 +64,10 @@ void AST_init() { lookup_table[AST_Typedef] = "typedef"; lookup_table[AST_Box] = "box"; lookup_table[AST_Fun] = "fun"; + + lookup_table[AST_Typecast] = "cast"; + lookup_table[AST_Transmute] = "as"; + lookup_table[AST_Condition] = "condition"; } const char* AST_node_to_string(struct AST_Node_t* node) { @@ -77,6 +82,7 @@ const char* AST_node_to_string(struct AST_Node_t* node) { case AST_Ident: case AST_Macro: case AST_Import: + case AST_Call: string = node->value; break; default: diff --git a/src/ast/ast.h b/src/ast/ast.h index 486a520..0bb9c6e 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -17,6 +17,7 @@ enum AST_SyntaxElement_t { AST_If, AST_IfElse, AST_Else, + AST_Condition, // Variable management AST_Decl, AST_Assign, diff --git a/tests/ast/CMakeLists.txt b/tests/ast/CMakeLists.txt index 81e7b96..455130b 100644 --- a/tests/ast/CMakeLists.txt +++ b/tests/ast/CMakeLists.txt @@ -24,12 +24,28 @@ add_test(NAME ast_build_tree add_executable(ast_print_node ${PROJECT_SOURCE_DIR}/src/ast/ast.c + ${PROJECT_SOURCE_DIR}/src/sys/log.c print_node.c) -set_target_properties(ast_build_tree +set_target_properties(ast_print_node PROPERTIES - OUTPUT_NAME "build_tree" + OUTPUT_NAME "print_node" RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/ast) add_test(NAME ast_print_node WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND python ${GEMSTONE_TEST_DIR}/ast/test_ast.py check_print_node) +# ------------------------------------------------------- # +# CTEST 3 +# test graphviz output + +add_executable(ast_graphviz + ${PROJECT_SOURCE_DIR}/src/ast/ast.c + ${PROJECT_SOURCE_DIR}/src/sys/log.c + print_graphviz.c) +set_target_properties(ast_graphviz + PROPERTIES + OUTPUT_NAME "print_graphviz" + RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/ast) +add_test(NAME ast_graphviz + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + COMMAND python ${GEMSTONE_TEST_DIR}/ast/test_ast.py check_print_graphviz) diff --git a/tests/ast/print_graphviz.c b/tests/ast/print_graphviz.c new file mode 100644 index 0000000..6df64b4 --- /dev/null +++ b/tests/ast/print_graphviz.c @@ -0,0 +1,54 @@ +// +// Created by servostar on 5/8/24. +// + +#include +#include + +void generate_statement(const AST_NODE_PTR stmt) { + const AST_NODE_PTR add = AST_new_node(AST_Add, NULL); + + AST_push_node(add, AST_new_node(AST_Int, "3")); + AST_push_node(add, AST_new_node(AST_Int, "6")); + + AST_push_node(stmt, add); +} + +void generate_branch(const AST_NODE_PTR stmt) { + const AST_NODE_PTR branch = AST_new_node(AST_If, NULL); + const AST_NODE_PTR gt = AST_new_node(AST_Greater, NULL); + + AST_push_node(branch, gt); + + AST_push_node(gt, AST_new_node(AST_Float, "2.3")); + AST_push_node(gt, AST_new_node(AST_Float, "0.79")); + + AST_push_node(stmt, branch); + + generate_statement(branch); +} + +int main(void) { + + AST_init(); + + const AST_NODE_PTR root = AST_new_node(AST_Stmt, NULL); + + generate_branch(root); + + FILE* output = fopen("tmp/graph.gv", "w"); + + if (output == NULL) { + PANIC("unable to open file"); + } + + AST_fprint_graphviz(output, root); + + fflush(output); + + fclose(output); + + AST_delete_node(root); + + return 0; +} diff --git a/tests/ast/print_node.c b/tests/ast/print_node.c index 83d3d43..38e8a41 100644 --- a/tests/ast/print_node.c +++ b/tests/ast/print_node.c @@ -6,6 +6,8 @@ int main(void) { + AST_init(); + const AST_NODE_PTR node = AST_new_node(0, "value"); for (size_t i = 0; i < AST_ELEMENT_COUNT; i++) { @@ -16,4 +18,6 @@ int main(void) { } AST_delete_node(node); + + return 0; } diff --git a/tests/ast/test_ast.py b/tests/ast/test_ast.py index 111e9c3..8acd654 100644 --- a/tests/ast/test_ast.py +++ b/tests/ast/test_ast.py @@ -28,6 +28,71 @@ def run_check_print_node(): # check exit code assert p.returncode == 0 + assert """0 stmt +1 expr +2 value +3 value +4 value +5 while +6 if +7 else if +8 else +9 condition +10 decl +11 assign +12 def +13 value +14 + +15 - +16 * +17 / +18 & +19 | +20 ^ +21 ! +22 && +23 || +24 ^^ +25 !! +26 == +27 > +28 < +29 cast +30 as +31 value +32 value +33 typedef +34 box +35 fun +36 value +""" == p.stdout + + +def run_check_print_graphviz(): + info("started check print graphviz...") + + p = subprocess.run(BIN_DIR + "print_graphviz", capture_output=True, text=True) + + info("checking exit code...") + + # check exit code + assert p.returncode == 0 + + info("converting gv to svg...") + + p = subprocess.run(["dot", "-Tsvg", "tmp/graph.gv", "-otmp/graph.svg"]) + + info("checking exit code...") + assert p.returncode == 0 + + info("checking svg output...") + with open("tmp/graph.svg", "r") as file: + string = "".join(file.readlines()) + assert "2.3" in string + assert "0.79" in string + assert "stmt" in string + assert "if" in string + if __name__ == "__main__": logging.basicConfig(level=logging.INFO) @@ -41,6 +106,8 @@ if __name__ == "__main__": run_check_build_tree() case "check_print_node": run_check_print_node() + case "check_print_graphviz": + run_check_print_graphviz() case _: error(f"unknown target: {target}") exit(1)