forked from GitHub/gf-core
graphvizAbstractTree in the C and Python runtimes
This commit is contained in:
@@ -47,6 +47,7 @@ pgfinclude_HEADERS = \
|
|||||||
pgf/parser.h \
|
pgf/parser.h \
|
||||||
pgf/lexer.h \
|
pgf/lexer.h \
|
||||||
pgf/literals.h \
|
pgf/literals.h \
|
||||||
|
pgf/graphviz.h \
|
||||||
pgf/pgf.h
|
pgf/pgf.h
|
||||||
|
|
||||||
libgu_la_SOURCES = \
|
libgu_la_SOURCES = \
|
||||||
@@ -115,6 +116,7 @@ libpgf_la_SOURCES = \
|
|||||||
pgf/linearizer.c \
|
pgf/linearizer.c \
|
||||||
pgf/reasoner.c \
|
pgf/reasoner.c \
|
||||||
pgf/printer.c \
|
pgf/printer.c \
|
||||||
|
pgf/graphviz.c \
|
||||||
pgf/pgf.c \
|
pgf/pgf.c \
|
||||||
pgf/pgf.h
|
pgf/pgf.h
|
||||||
|
|
||||||
|
|||||||
93
src/runtime/c/pgf/graphviz.c
Normal file
93
src/runtime/c/pgf/graphviz.c
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
#include "data.h"
|
||||||
|
#include "graphviz.h"
|
||||||
|
|
||||||
|
static int
|
||||||
|
pgf_graphviz_abstract_tree_(PgfExpr expr, int *pid,
|
||||||
|
GuWriter* wtr, GuExn* err)
|
||||||
|
{
|
||||||
|
int id = -1;
|
||||||
|
|
||||||
|
GuVariantInfo ei = gu_variant_open(expr);
|
||||||
|
switch (ei.tag) {
|
||||||
|
case PGF_EXPR_ABS:
|
||||||
|
gu_impossible();
|
||||||
|
break;
|
||||||
|
case PGF_EXPR_APP: {
|
||||||
|
PgfExprApp* app = ei.data;
|
||||||
|
id = pgf_graphviz_abstract_tree_(app->fun, pid, wtr, err);
|
||||||
|
int arg_id = pgf_graphviz_abstract_tree_(app->arg, pid, wtr, err);
|
||||||
|
gu_printf(wtr, err, "n%d -- n%d [style = \"solid\"]\n", id, arg_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PGF_EXPR_LIT: {
|
||||||
|
PgfExprLit* lit = ei.data;
|
||||||
|
id = (*pid)++;
|
||||||
|
gu_printf(wtr, err, "n%d[label = \"", id);
|
||||||
|
|
||||||
|
GuVariantInfo ei = gu_variant_open(lit->lit);
|
||||||
|
switch (ei.tag) {
|
||||||
|
case PGF_LITERAL_STR: {
|
||||||
|
PgfLiteralStr* lit = ei.data;
|
||||||
|
gu_puts("\\\"", wtr, err);
|
||||||
|
gu_string_write(lit->val, wtr, err);
|
||||||
|
gu_puts("\\\"", wtr, err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PGF_LITERAL_INT: {
|
||||||
|
PgfLiteralInt* lit = ei.data;
|
||||||
|
gu_printf(wtr, err, "%d", lit->val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PGF_LITERAL_FLT: {
|
||||||
|
PgfLiteralFlt* lit = ei.data;
|
||||||
|
gu_printf(wtr, err, "%lf", lit->val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
gu_impossible();
|
||||||
|
}
|
||||||
|
|
||||||
|
gu_puts("\", style = \"solid\", shape = \"plaintext\"]\n", wtr, err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PGF_EXPR_META:
|
||||||
|
id = (*pid)++;
|
||||||
|
gu_printf(wtr, err, "n%d[label = \"?\", style = \"solid\", shape = \"plaintext\"]\n", id);
|
||||||
|
break;
|
||||||
|
case PGF_EXPR_FUN: {
|
||||||
|
PgfExprFun* fun = ei.data;
|
||||||
|
id = (*pid)++;
|
||||||
|
gu_printf(wtr, err, "n%d[label = \"", id);
|
||||||
|
gu_string_write(fun->fun, wtr, err);
|
||||||
|
gu_puts("\", style = \"solid\", shape = \"plaintext\"]\n", wtr, err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PGF_EXPR_VAR:
|
||||||
|
gu_impossible();
|
||||||
|
break;
|
||||||
|
case PGF_EXPR_TYPED: {
|
||||||
|
PgfExprTyped* typed = ei.data;
|
||||||
|
id = pgf_graphviz_abstract_tree_(typed->expr, pid, wtr, err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PGF_EXPR_IMPL_ARG: {
|
||||||
|
PgfExprImplArg* implarg = ei.data;
|
||||||
|
id = pgf_graphviz_abstract_tree_(implarg->expr, pid, wtr, err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
gu_impossible();
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pgf_graphviz_abstract_tree(PgfExpr expr, GuWriter* wtr, GuExn* err)
|
||||||
|
{
|
||||||
|
int id = 0;
|
||||||
|
|
||||||
|
gu_puts("graph {\n", wtr, err);
|
||||||
|
pgf_graphviz_abstract_tree_(expr, &id, wtr, err);
|
||||||
|
gu_puts("}", wtr, err);
|
||||||
|
}
|
||||||
7
src/runtime/c/pgf/graphviz.h
Normal file
7
src/runtime/c/pgf/graphviz.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef PGF_GRAPHVIZ_H_
|
||||||
|
#define PGF_GRAPHVIZ_H_
|
||||||
|
|
||||||
|
void
|
||||||
|
pgf_graphviz_abstract_tree(PgfExpr expr, GuWriter* wtr, GuExn* err);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -55,87 +55,6 @@ url_escape(char *str)
|
|||||||
*pw++ = 0;
|
*pw++ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
generate_graphviz_expr(PgfExpr expr, int *pid,
|
|
||||||
GuWriter* wtr, GuExn* err, GuPool* pool)
|
|
||||||
{
|
|
||||||
int id = -1;
|
|
||||||
|
|
||||||
GuVariantInfo ei = gu_variant_open(expr);
|
|
||||||
switch (ei.tag) {
|
|
||||||
case PGF_EXPR_FUN: {
|
|
||||||
PgfExprFun* fun = ei.data;
|
|
||||||
id = (*pid)++;
|
|
||||||
gu_printf(wtr, err, "n%d[label = \"", id);
|
|
||||||
gu_string_write(fun->fun, wtr, err);
|
|
||||||
gu_puts("\", style = \"solid\", shape = \"plaintext\"]\n", wtr, err);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PGF_EXPR_APP: {
|
|
||||||
PgfExprApp* app = ei.data;
|
|
||||||
id = generate_graphviz_expr(app->fun, pid, wtr, err, pool);
|
|
||||||
int arg_id = generate_graphviz_expr(app->arg, pid, wtr, err, pool);
|
|
||||||
gu_printf(wtr, err, "n%d -- n%d [style = \"solid\"]\n", id, arg_id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PGF_EXPR_ABS:
|
|
||||||
case PGF_EXPR_LIT: {
|
|
||||||
PgfExprLit* lit = ei.data;
|
|
||||||
id = (*pid)++;
|
|
||||||
gu_printf(wtr, err, "n%d[label = \"", id);
|
|
||||||
|
|
||||||
GuVariantInfo ei = gu_variant_open(lit->lit);
|
|
||||||
switch (ei.tag) {
|
|
||||||
case PGF_LITERAL_STR: {
|
|
||||||
PgfLiteralStr* lit = ei.data;
|
|
||||||
gu_puts("\\\"", wtr, err);
|
|
||||||
gu_string_write(lit->val, wtr, err);
|
|
||||||
gu_puts("\\\"", wtr, err);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PGF_LITERAL_INT: {
|
|
||||||
PgfLiteralInt* lit = ei.data;
|
|
||||||
gu_printf(wtr, err, "%d", lit->val);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PGF_LITERAL_FLT: {
|
|
||||||
PgfLiteralFlt* lit = ei.data;
|
|
||||||
gu_printf(wtr, err, "%lf", lit->val);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
gu_impossible();
|
|
||||||
}
|
|
||||||
|
|
||||||
gu_puts("\", style = \"solid\", shape = \"plaintext\"]\n", wtr, err);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PGF_EXPR_META:
|
|
||||||
id = (*pid)++;
|
|
||||||
gu_printf(wtr, err, "n%d[label = \"?\", style = \"solid\", shape = \"plaintext\"]\n", id);
|
|
||||||
break;
|
|
||||||
case PGF_EXPR_VAR:
|
|
||||||
case PGF_EXPR_TYPED:
|
|
||||||
case PGF_EXPR_IMPL_ARG:
|
|
||||||
gu_impossible();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
gu_impossible();
|
|
||||||
}
|
|
||||||
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
generate_graphviz(PgfExpr expr, GuWriter* wtr, GuExn* err, GuPool* pool)
|
|
||||||
{
|
|
||||||
int id = 0;
|
|
||||||
|
|
||||||
gu_puts("graph {\n", wtr, err);
|
|
||||||
generate_graphviz_expr(expr, &id, wtr, err, pool);
|
|
||||||
gu_puts("}", wtr, err);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
render(PgfExpr expr, GuPool* pool)
|
render(PgfExpr expr, GuPool* pool)
|
||||||
{
|
{
|
||||||
@@ -175,7 +94,7 @@ render(PgfExpr expr, GuPool* pool)
|
|||||||
GuWriter* wtr = gu_new_utf8_writer(out, pool);
|
GuWriter* wtr = gu_new_utf8_writer(out, pool);
|
||||||
GuExn* err = gu_new_exn(NULL, gu_kind(type), pool);
|
GuExn* err = gu_new_exn(NULL, gu_kind(type), pool);
|
||||||
|
|
||||||
generate_graphviz(expr, wtr, err, pool);
|
pgf_graphviz_abstract_tree(expr, wtr, err);
|
||||||
fclose(fstream);
|
fclose(fstream);
|
||||||
|
|
||||||
close(cp[1]);
|
close(cp[1]);
|
||||||
|
|||||||
@@ -2215,6 +2215,30 @@ pgf_readType(PyObject *self, PyObject *args) {
|
|||||||
return pytype;
|
return pytype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
pgf_graphvizAbstractTree(PyObject *self, PyObject *args) {
|
||||||
|
ExprObject* pyexpr;
|
||||||
|
if (!PyArg_ParseTuple(args, "O!", &pgf_ExprType, &pyexpr))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
GuPool* tmp_pool = gu_local_pool();
|
||||||
|
GuExn* err = gu_new_exn(NULL, gu_kind(type), tmp_pool);
|
||||||
|
GuStringBuf* sbuf = gu_string_buf(tmp_pool);
|
||||||
|
GuWriter* wtr = gu_string_buf_writer(sbuf);
|
||||||
|
|
||||||
|
pgf_graphviz_abstract_tree(pyexpr->expr, wtr, err);
|
||||||
|
if (!gu_ok(err)) {
|
||||||
|
PyErr_SetString(PGFError, "The abstract tree cannot be visualized");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
GuString str = gu_string_buf_freeze(sbuf, tmp_pool);
|
||||||
|
PyObject* pystr = gu2py_string(str);
|
||||||
|
|
||||||
|
gu_pool_free(tmp_pool);
|
||||||
|
return pystr;
|
||||||
|
}
|
||||||
|
|
||||||
static PyMethodDef module_methods[] = {
|
static PyMethodDef module_methods[] = {
|
||||||
{"readPGF", (void*)pgf_readPGF, METH_VARARGS,
|
{"readPGF", (void*)pgf_readPGF, METH_VARARGS,
|
||||||
"Reads a PGF file in memory"},
|
"Reads a PGF file in memory"},
|
||||||
@@ -2222,6 +2246,8 @@ static PyMethodDef module_methods[] = {
|
|||||||
"Parses a string as an abstract tree"},
|
"Parses a string as an abstract tree"},
|
||||||
{"readType", (void*)pgf_readType, METH_VARARGS,
|
{"readType", (void*)pgf_readType, METH_VARARGS,
|
||||||
"Parses a string as an abstract type"},
|
"Parses a string as an abstract type"},
|
||||||
|
{"graphvizAbstractTree", (void*)pgf_graphvizAbstractTree, METH_VARARGS,
|
||||||
|
"Renders an abstract syntax tree in a Graphviz format"},
|
||||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user