#include "t.h" #include "cf.h" #include "dc.h" #include "js.h" #include "p.h" #include "str.h" static void snap_node(tobi_sb *sb, const tobi_ir *n) { tobi_sb_printf(sb, "%zu:%zu:", n->id, n->parent_id); if (n->parent_id == 0) { tobi_sb_add(sb, "-"); } else { tobi_sb_printf(sb, "%zu", n->parent_index); } tobi_sb_printf(sb, ":%s", tobi_ir_kind_name(n->kind)); if (n->name) { tobi_sb_printf(sb, ":%s", n->name); } if (n->scope) { tobi_sb_printf(sb, ":scope=%s", n->scope); } tobi_sb_ch(sb, '\n'); for (size_t i = 0; i < n->child_len; i++) { snap_node(sb, n->child[i]); } } static char *snapshot(const tobi_ir *root) { tobi_sb sb; tobi_sb_init(&sb); snap_node(&sb, root); return tobi_sb_take(&sb); } int t_snap(void) { uint8_t m0[] = {0x14,0x0c,'M','T','H','0',0x01,0x70,0x0a,0x2a,0x60,0xa4,0x60}; tobi_parse_result r; T_CHECK(tobi_parse(m0, sizeof(m0), 0, &r)); T_CHECK(tobi_cf_recover(r.root, &r.diag)); char *s = snapshot(r.root); const char *want = "1:0:-:root:scope=\\\n" "2:1:0:method:MTH0\n" "3:2:0:block:scope=\\MTH0\n" "4:3:0:store\n" "5:4:0:integer\n" "6:4:1:ref:Local0\n" "7:3:1:return\n" "8:7:0:ref:Local0\n"; T_CHECK(strcmp(s, want) == 0); free(s); char *j = tobi_js_emit(&r); T_STR(j, "\"id\":1"); T_STR(j, "\"parent_id\":1"); T_STR(j, "\"parent_index\":0"); T_STR(j, "\"scope\":\"\\\\MTH0\""); T_CHECK(strstr(j, ",}") == NULL); T_CHECK(strstr(j, ",]") == NULL); free(j); char *d = tobi_dc_emit(r.root, &r.diag); const char *dwant = "method MTH0(args=1, serialized=false, sync=0) {\n" " Local0 = 0x2a;\n" " return Local0;\n" "}\n"; T_CHECK(strcmp(d, dwant) == 0); free(d); char *g = tobi_graph_dot(r.root, &r.ns, TOBI_GRAPH_CFG); const char *cfg_want = "digraph tobi_cfg {\n" " graph [rankdir=TB,bgcolor=\"#ffffff\",pad=0.18,nodesep=0.5,ranksep=0.72,splines=ortho,outputorder=edgesfirst];\n" " node [shape=box,style=\"solid\",color=\"#000000\",fontcolor=\"#000000\",fontname=\"Courier\",fontsize=12,margin=\"0.12,0.07\",penwidth=1.1];\n" " edge [color=\"#000000\",fontcolor=\"#000000\",arrowsize=0.75,penwidth=1.1];\n" " n0 [label=\"root\\noff=0x0\"];\n" " n1 [label=\"method\\nMTH0\\noff=0x0\"];\n" " n2 [label=\"store\\noff=0x7\"];\n" " e0 [shape=box,style=\"solid\",color=\"#000000\",fontcolor=\"#000000\",fontname=\"Times-Roman\",fontsize=10,margin=\"0.06,0.03\",height=0,width=0,label=\"entry\"];\n" " n1 -> e0 [arrowhead=none, weight=2];\n" " e0 -> n2 [weight=2];\n" " n3 [label=\"return\\noff=0xb\"];\n" " e1 [shape=box,style=\"solid\",color=\"#000000\",fontcolor=\"#000000\",fontname=\"Times-Roman\",fontsize=10,margin=\"0.06,0.03\",height=0,width=0,label=\"next\"];\n" " n2 -> e1 [arrowhead=none, weight=2];\n" " e1 -> n3 [weight=2];\n" " e2 [shape=box,style=\"solid\",color=\"#000000\",fontcolor=\"#000000\",fontname=\"Times-Roman\",fontsize=10,margin=\"0.06,0.03\",height=0,width=0,label=\"entry\"];\n" " n0 -> e2 [arrowhead=none, weight=2];\n" " e2 -> n1 [weight=2];\n" "}\n"; T_CHECK(strcmp(g, cfg_want) == 0); free(g); g = tobi_graph_dot(r.root, &r.ns, TOBI_GRAPH_AST); const char *ast_want = "digraph tobi_ast {\n" " graph [rankdir=TB,bgcolor=\"#ffffff\",pad=0.18,nodesep=0.5,ranksep=0.72,splines=ortho,outputorder=edgesfirst];\n" " node [shape=box,style=\"solid\",color=\"#000000\",fontcolor=\"#000000\",fontname=\"Courier\",fontsize=12,margin=\"0.12,0.07\",penwidth=1.1];\n" " edge [color=\"#000000\",fontcolor=\"#000000\",arrowsize=0.75,penwidth=1.1];\n" " n0 [label=\"root\\noff=0x0\"];\n" " n1 [label=\"method\\nMTH0\\noff=0x0\"];\n" " n2 [label=\"block\\noff=0x7\"];\n" " n3 [label=\"store\\noff=0x7\"];\n" " n4 [label=\"integer\\noff=0x8\"];\n" " n3 -> n4;\n" " n5 [label=\"ref\\nLocal0\\noff=0xa\"];\n" " n3 -> n5;\n" " n2 -> n3;\n" " n6 [label=\"return\\noff=0xb\"];\n" " n7 [label=\"ref\\nLocal0\\noff=0xc\"];\n" " n6 -> n7;\n" " n2 -> n6;\n" " n1 -> n2;\n" " n0 -> n1;\n" "}\n"; T_CHECK(strcmp(g, ast_want) == 0); free(g); g = tobi_graph_dot(r.root, &r.ns, TOBI_GRAPH_NAMESPACE); const char *ns_want = "digraph tobi_namespace {\n" " graph [rankdir=TB,bgcolor=\"#ffffff\",pad=0.18,nodesep=0.5,ranksep=0.72,splines=ortho,outputorder=edgesfirst];\n" " node [shape=box,style=\"solid\",color=\"#000000\",fontcolor=\"#000000\",fontname=\"Courier\",fontsize=12,margin=\"0.12,0.07\",penwidth=1.1];\n" " edge [color=\"#000000\",fontcolor=\"#000000\",arrowsize=0.75,penwidth=1.1];\n" " n0 [label=\"namespace\\n\\\\\"];\n" " n1 [label=\"method\\nMTH0\\n\\\\MTH0\\noff=0x0\"];\n" " n0 -> n1;\n" "}\n"; T_CHECK(strcmp(g, ns_want) == 0); free(g); tobi_parse_result_free(&r); uint8_t nested[] = { 0x10,0x14,'\\','_','S','B','_',0x5b,0x82,0x0c,'D','E','V','0', 0x14,0x06,'M','0','0','0',0x00 }; T_CHECK(tobi_parse(nested, sizeof(nested), 0, &r)); T_CHECK(strcmp(r.root->scope, "\\") == 0); T_CHECK(strcmp(r.root->child[0]->child[0]->scope, "\\_SB_") == 0); T_CHECK(strcmp(r.root->child[0]->child[0]->child[0]->child[0]->scope, "\\_SB_.DEV0") == 0); T_CHECK(strcmp(r.root->child[0]->child[0]->child[0]->child[0]->child[0]->child[0]->scope, "\\_SB_.DEV0.M000") == 0); T_CHECK(r.root->child[0]->id == 2); T_CHECK(r.root->child[0]->child[0]->parent_id == r.root->child[0]->id); tobi_parse_result_free(&r); return 0; }