mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-22 19:22:50 -06:00
a complete Python API for reading, printing and manipulation of abstract trees and types. This includes dependent types, high-order abstract syntax and implicit arguments
This commit is contained in:
@@ -88,7 +88,7 @@ GU_DEFINE_TYPE(PgfLiteral, GuVariant,
|
|||||||
GU_DECLARE_TYPE(PgfType, struct);
|
GU_DECLARE_TYPE(PgfType, struct);
|
||||||
|
|
||||||
GU_DEFINE_TYPE(PgfHypo, struct,
|
GU_DEFINE_TYPE(PgfHypo, struct,
|
||||||
GU_MEMBER(PgfHypo, bindtype, PgfBindType),
|
GU_MEMBER(PgfHypo, bind_type, PgfBindType),
|
||||||
GU_MEMBER(PgfHypo, cid, PgfCId),
|
GU_MEMBER(PgfHypo, cid, PgfCId),
|
||||||
GU_MEMBER_P(PgfHypo, type, PgfType));
|
GU_MEMBER_P(PgfHypo, type, PgfType));
|
||||||
|
|
||||||
@@ -137,7 +137,16 @@ typedef struct PgfExprParser PgfExprParser;
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
PGF_TOKEN_LPAR,
|
PGF_TOKEN_LPAR,
|
||||||
PGF_TOKEN_RPAR,
|
PGF_TOKEN_RPAR,
|
||||||
|
PGF_TOKEN_LCURLY,
|
||||||
|
PGF_TOKEN_RCURLY,
|
||||||
PGF_TOKEN_QUESTION,
|
PGF_TOKEN_QUESTION,
|
||||||
|
PGF_TOKEN_LAMBDA,
|
||||||
|
PGF_TOKEN_RARROW,
|
||||||
|
PGF_TOKEN_LTRIANGLE,
|
||||||
|
PGF_TOKEN_RTRIANGLE,
|
||||||
|
PGF_TOKEN_COMMA,
|
||||||
|
PGF_TOKEN_COLON,
|
||||||
|
PGF_TOKEN_WILD,
|
||||||
PGF_TOKEN_IDENT,
|
PGF_TOKEN_IDENT,
|
||||||
PGF_TOKEN_INT,
|
PGF_TOKEN_INT,
|
||||||
PGF_TOKEN_FLT,
|
PGF_TOKEN_FLT,
|
||||||
@@ -172,11 +181,6 @@ pgf_expr_parser_token(PgfExprParser* parser)
|
|||||||
while (isspace(parser->ch)) {
|
while (isspace(parser->ch)) {
|
||||||
pgf_expr_parser_getc(parser);
|
pgf_expr_parser_getc(parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parser->tmp_pool != NULL) {
|
|
||||||
gu_pool_free(parser->tmp_pool);
|
|
||||||
parser->tmp_pool = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
parser->token_tag = PGF_TOKEN_UNKNOWN;
|
parser->token_tag = PGF_TOKEN_UNKNOWN;
|
||||||
parser->token_value = gu_null_seq;
|
parser->token_value = gu_null_seq;
|
||||||
@@ -193,12 +197,50 @@ pgf_expr_parser_token(PgfExprParser* parser)
|
|||||||
pgf_expr_parser_getc(parser);
|
pgf_expr_parser_getc(parser);
|
||||||
parser->token_tag = PGF_TOKEN_RPAR;
|
parser->token_tag = PGF_TOKEN_RPAR;
|
||||||
break;
|
break;
|
||||||
|
case '{':
|
||||||
|
pgf_expr_parser_getc(parser);
|
||||||
|
parser->token_tag = PGF_TOKEN_LCURLY;
|
||||||
|
break;
|
||||||
|
case '}':
|
||||||
|
pgf_expr_parser_getc(parser);
|
||||||
|
parser->token_tag = PGF_TOKEN_RCURLY;
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
pgf_expr_parser_getc(parser);
|
||||||
|
parser->token_tag = PGF_TOKEN_LTRIANGLE;
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
pgf_expr_parser_getc(parser);
|
||||||
|
parser->token_tag = PGF_TOKEN_RTRIANGLE;
|
||||||
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
pgf_expr_parser_getc(parser);
|
pgf_expr_parser_getc(parser);
|
||||||
parser->token_tag = PGF_TOKEN_QUESTION;
|
parser->token_tag = PGF_TOKEN_QUESTION;
|
||||||
break;
|
break;
|
||||||
|
case '\\':
|
||||||
|
pgf_expr_parser_getc(parser);
|
||||||
|
parser->token_tag = PGF_TOKEN_LAMBDA;
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
pgf_expr_parser_getc(parser);
|
||||||
|
if (parser->ch == '>') {
|
||||||
|
pgf_expr_parser_getc(parser);
|
||||||
|
parser->token_tag = PGF_TOKEN_RARROW;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ',':
|
||||||
|
pgf_expr_parser_getc(parser);
|
||||||
|
parser->token_tag = PGF_TOKEN_COMMA;
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
pgf_expr_parser_getc(parser);
|
||||||
|
parser->token_tag = PGF_TOKEN_COLON;
|
||||||
|
break;
|
||||||
|
case '_':
|
||||||
|
pgf_expr_parser_getc(parser);
|
||||||
|
parser->token_tag = PGF_TOKEN_WILD;
|
||||||
|
break;
|
||||||
default: {
|
default: {
|
||||||
parser->tmp_pool = gu_new_pool();
|
|
||||||
GuCharBuf* chars = gu_new_buf(char, parser->tmp_pool);
|
GuCharBuf* chars = gu_new_buf(char, parser->tmp_pool);
|
||||||
|
|
||||||
if (isalpha(parser->ch)) {
|
if (isalpha(parser->ch)) {
|
||||||
@@ -249,9 +291,22 @@ pgf_expr_parser_token(PgfExprParser* parser)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
pgf_expr_parser_lookahead(PgfExprParser* parser, int ch)
|
||||||
|
{
|
||||||
|
while (isspace(parser->ch)) {
|
||||||
|
pgf_expr_parser_getc(parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (parser->ch == ch);
|
||||||
|
}
|
||||||
|
|
||||||
static PgfExpr
|
static PgfExpr
|
||||||
pgf_expr_parser_expr(PgfExprParser* parser);
|
pgf_expr_parser_expr(PgfExprParser* parser);
|
||||||
|
|
||||||
|
static PgfType*
|
||||||
|
pgf_expr_parser_type(PgfExprParser* parser);
|
||||||
|
|
||||||
static PgfExpr
|
static PgfExpr
|
||||||
pgf_expr_parser_term(PgfExprParser* parser)
|
pgf_expr_parser_term(PgfExprParser* parser)
|
||||||
{
|
{
|
||||||
@@ -266,6 +321,27 @@ pgf_expr_parser_term(PgfExprParser* parser)
|
|||||||
return gu_null_variant;
|
return gu_null_variant;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case PGF_TOKEN_LTRIANGLE: {
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
PgfExpr expr = pgf_expr_parser_expr(parser);
|
||||||
|
|
||||||
|
if (parser->token_tag != PGF_TOKEN_COLON) {
|
||||||
|
return gu_null_variant;
|
||||||
|
}
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
|
||||||
|
PgfType* type = pgf_expr_parser_type(parser);
|
||||||
|
|
||||||
|
if (parser->token_tag != PGF_TOKEN_RTRIANGLE) {
|
||||||
|
return gu_null_variant;
|
||||||
|
}
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
|
||||||
|
return gu_new_variant_i(parser->expr_pool,
|
||||||
|
PGF_EXPR_TYPED,
|
||||||
|
PgfExprTyped,
|
||||||
|
expr, type);
|
||||||
|
}
|
||||||
case PGF_TOKEN_QUESTION: {
|
case PGF_TOKEN_QUESTION: {
|
||||||
pgf_expr_parser_token(parser);
|
pgf_expr_parser_token(parser);
|
||||||
return gu_new_variant_i(parser->expr_pool,
|
return gu_new_variant_i(parser->expr_pool,
|
||||||
@@ -333,41 +409,354 @@ pgf_expr_parser_term(PgfExprParser* parser)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PgfExpr
|
||||||
|
pgf_expr_parser_arg(PgfExprParser* parser)
|
||||||
|
{
|
||||||
|
PgfExpr arg;
|
||||||
|
|
||||||
|
if (parser->token_tag == PGF_TOKEN_LCURLY) {
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
|
||||||
|
arg = pgf_expr_parser_expr(parser);
|
||||||
|
if (gu_variant_is_null(arg))
|
||||||
|
return gu_null_variant;
|
||||||
|
|
||||||
|
if (parser->token_tag != PGF_TOKEN_RCURLY) {
|
||||||
|
return gu_null_variant;
|
||||||
|
}
|
||||||
|
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
|
||||||
|
arg = gu_new_variant_i(parser->expr_pool,
|
||||||
|
PGF_EXPR_IMPL_ARG,
|
||||||
|
PgfExprImplArg,
|
||||||
|
arg);
|
||||||
|
} else {
|
||||||
|
arg = pgf_expr_parser_term(parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
pgf_expr_parser_bind(PgfExprParser* parser, GuBuf* binds)
|
||||||
|
{
|
||||||
|
PgfCId var;
|
||||||
|
PgfBindType bind_type = PGF_BIND_TYPE_EXPLICIT;
|
||||||
|
|
||||||
|
if (parser->token_tag == PGF_TOKEN_LCURLY) {
|
||||||
|
bind_type = PGF_BIND_TYPE_IMPLICIT;
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (parser->token_tag == PGF_TOKEN_IDENT) {
|
||||||
|
char* str =
|
||||||
|
gu_chars_str(parser->token_value, parser->tmp_pool);
|
||||||
|
var = gu_str_string(str, parser->expr_pool);
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
} else if (parser->token_tag == PGF_TOKEN_WILD) {
|
||||||
|
var = gu_str_string("_", parser->expr_pool);
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PgfExpr bind =
|
||||||
|
gu_new_variant_i(parser->expr_pool,
|
||||||
|
PGF_EXPR_ABS,
|
||||||
|
PgfExprAbs,
|
||||||
|
bind_type,
|
||||||
|
var,
|
||||||
|
gu_null_variant);
|
||||||
|
gu_buf_push(binds, PgfExpr, bind);
|
||||||
|
|
||||||
|
if (bind_type == PGF_BIND_TYPE_EXPLICIT ||
|
||||||
|
parser->token_tag != PGF_TOKEN_COMMA) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bind_type == PGF_BIND_TYPE_IMPLICIT) {
|
||||||
|
if (parser->token_tag != PGF_TOKEN_RCURLY)
|
||||||
|
return false;
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GuBuf*
|
||||||
|
pgf_expr_parser_binds(PgfExprParser* parser)
|
||||||
|
{
|
||||||
|
GuBuf* binds = gu_new_buf(PgfExpr, parser->tmp_pool);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (!pgf_expr_parser_bind(parser, binds))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (parser->token_tag != PGF_TOKEN_COMMA)
|
||||||
|
break;
|
||||||
|
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
return binds;
|
||||||
|
}
|
||||||
|
|
||||||
static PgfExpr
|
static PgfExpr
|
||||||
pgf_expr_parser_expr(PgfExprParser* parser)
|
pgf_expr_parser_expr(PgfExprParser* parser)
|
||||||
{
|
{
|
||||||
PgfExpr expr = pgf_expr_parser_term(parser);
|
if (parser->token_tag == PGF_TOKEN_LAMBDA) {
|
||||||
if (gu_variant_is_null(expr))
|
pgf_expr_parser_token(parser);
|
||||||
return expr;
|
GuBuf* binds = pgf_expr_parser_binds(parser);
|
||||||
|
if (binds == NULL)
|
||||||
|
return gu_null_variant;
|
||||||
|
|
||||||
while (true) {
|
if (parser->token_tag != PGF_TOKEN_RARROW) {
|
||||||
PgfExpr arg = pgf_expr_parser_term(parser);
|
return gu_null_variant;
|
||||||
if (gu_variant_is_null(arg)) {
|
|
||||||
return expr;
|
|
||||||
}
|
}
|
||||||
expr = gu_new_variant_i(parser->expr_pool,
|
pgf_expr_parser_token(parser);
|
||||||
PGF_EXPR_APP,
|
|
||||||
PgfExprApp,
|
PgfExpr expr = pgf_expr_parser_expr(parser);
|
||||||
expr, arg);
|
if (gu_variant_is_null(expr))
|
||||||
|
return gu_null_variant;
|
||||||
|
|
||||||
|
size_t n_binds = gu_buf_length(binds);
|
||||||
|
for (size_t i = n_binds; i > 0; i--) {
|
||||||
|
PgfExpr bind = gu_buf_get(binds, PgfExpr, i-1);
|
||||||
|
|
||||||
|
((PgfExprAbs*) gu_variant_data(bind))->body = expr;
|
||||||
|
expr = bind;
|
||||||
|
}
|
||||||
|
|
||||||
|
return expr;
|
||||||
|
} else {
|
||||||
|
PgfExpr expr = pgf_expr_parser_term(parser);
|
||||||
|
if (gu_variant_is_null(expr))
|
||||||
|
return gu_null_variant;
|
||||||
|
|
||||||
|
while (parser->token_tag != PGF_TOKEN_EOF &&
|
||||||
|
parser->token_tag != PGF_TOKEN_RPAR &&
|
||||||
|
parser->token_tag != PGF_TOKEN_RCURLY &&
|
||||||
|
parser->token_tag != PGF_TOKEN_RTRIANGLE &&
|
||||||
|
parser->token_tag != PGF_TOKEN_COLON) {
|
||||||
|
PgfExpr arg = pgf_expr_parser_arg(parser);
|
||||||
|
if (gu_variant_is_null(arg))
|
||||||
|
return gu_null_variant;
|
||||||
|
|
||||||
|
expr = gu_new_variant_i(parser->expr_pool,
|
||||||
|
PGF_EXPR_APP,
|
||||||
|
PgfExprApp,
|
||||||
|
expr, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return expr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
pgf_expr_parser_hypos(PgfExprParser* parser, GuBuf* hypos)
|
||||||
|
{
|
||||||
|
PgfCId var;
|
||||||
|
PgfBindType bind_type = PGF_BIND_TYPE_EXPLICIT;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (bind_type == PGF_BIND_TYPE_EXPLICIT &&
|
||||||
|
parser->token_tag == PGF_TOKEN_LCURLY) {
|
||||||
|
bind_type = PGF_BIND_TYPE_IMPLICIT;
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parser->token_tag == PGF_TOKEN_IDENT) {
|
||||||
|
char* str =
|
||||||
|
gu_chars_str(parser->token_value, parser->tmp_pool);
|
||||||
|
var = gu_str_string(str, parser->expr_pool);
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
} else if (parser->token_tag == PGF_TOKEN_WILD) {
|
||||||
|
var = gu_str_string("_", parser->expr_pool);
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PgfHypo* hypo = gu_buf_extend(hypos);
|
||||||
|
hypo->bind_type = bind_type;
|
||||||
|
hypo->cid = var;
|
||||||
|
hypo->type = NULL;
|
||||||
|
|
||||||
|
if (bind_type == PGF_BIND_TYPE_IMPLICIT &&
|
||||||
|
parser->token_tag == PGF_TOKEN_RCURLY) {
|
||||||
|
bind_type = PGF_BIND_TYPE_EXPLICIT;
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parser->token_tag != PGF_TOKEN_COMMA) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bind_type == PGF_BIND_TYPE_IMPLICIT)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PgfType*
|
||||||
|
pgf_expr_parser_atom(PgfExprParser* parser)
|
||||||
|
{
|
||||||
|
if (parser->token_tag != PGF_TOKEN_IDENT)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
char* str =
|
||||||
|
gu_chars_str(parser->token_value, parser->tmp_pool);
|
||||||
|
PgfCId cid = gu_str_string(str, parser->expr_pool);
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
|
||||||
|
GuBuf* args = gu_new_buf(PgfExpr, parser->tmp_pool);
|
||||||
|
while (parser->token_tag != PGF_TOKEN_EOF &&
|
||||||
|
parser->token_tag != PGF_TOKEN_RPAR &&
|
||||||
|
parser->token_tag != PGF_TOKEN_RTRIANGLE &&
|
||||||
|
parser->token_tag != PGF_TOKEN_RARROW) {
|
||||||
|
PgfExpr arg =
|
||||||
|
pgf_expr_parser_arg(parser);
|
||||||
|
if (gu_variant_is_null(arg))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
gu_buf_push(args, PgfExpr, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t n_exprs = gu_buf_length(args);
|
||||||
|
|
||||||
|
PgfType* type = gu_new_flex(parser->expr_pool, PgfType, exprs, n_exprs);
|
||||||
|
type->hypos = gu_empty_seq();
|
||||||
|
type->cid = cid;
|
||||||
|
type->n_exprs = n_exprs;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n_exprs; i++) {
|
||||||
|
type->exprs[i] = gu_buf_get(args, PgfExpr, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PgfType*
|
||||||
|
pgf_expr_parser_type(PgfExprParser* parser)
|
||||||
|
{
|
||||||
|
PgfType* type = NULL;
|
||||||
|
GuBuf* hypos = gu_new_buf(PgfHypo, parser->expr_pool);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (parser->token_tag == PGF_TOKEN_LPAR) {
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
|
||||||
|
size_t n_start = gu_buf_length(hypos);
|
||||||
|
|
||||||
|
if ((parser->token_tag == PGF_TOKEN_IDENT &&
|
||||||
|
(pgf_expr_parser_lookahead(parser, ',') ||
|
||||||
|
pgf_expr_parser_lookahead(parser, ':'))) ||
|
||||||
|
(parser->token_tag == PGF_TOKEN_LCURLY) ||
|
||||||
|
(parser->token_tag == PGF_TOKEN_WILD)) {
|
||||||
|
|
||||||
|
if (!pgf_expr_parser_hypos(parser, hypos))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (parser->token_tag != PGF_TOKEN_COLON)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
} else {
|
||||||
|
PgfHypo* hypo = gu_buf_extend(hypos);
|
||||||
|
hypo->bind_type = PGF_BIND_TYPE_EXPLICIT;
|
||||||
|
hypo->cid = gu_str_string("_", parser->expr_pool);
|
||||||
|
hypo->type = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t n_end = gu_buf_length(hypos);
|
||||||
|
|
||||||
|
PgfType* type = pgf_expr_parser_type(parser);
|
||||||
|
if (type == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (parser->token_tag != PGF_TOKEN_RPAR)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
|
||||||
|
if (parser->token_tag != PGF_TOKEN_RARROW)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
|
||||||
|
for (size_t i = n_start; i < n_end; i++) {
|
||||||
|
PgfHypo* hypo = gu_buf_index(hypos, PgfHypo, i);
|
||||||
|
hypo->type = type;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
type = pgf_expr_parser_atom(parser);
|
||||||
|
if (type == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (parser->token_tag != PGF_TOKEN_RARROW)
|
||||||
|
break;
|
||||||
|
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
|
||||||
|
PgfHypo* hypo = gu_buf_extend(hypos);
|
||||||
|
hypo->bind_type = PGF_BIND_TYPE_EXPLICIT;
|
||||||
|
hypo->cid = gu_str_string("_", parser->expr_pool);
|
||||||
|
hypo->type = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type->hypos = gu_buf_seq(hypos);
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PgfExprParser*
|
||||||
|
pgf_new_parser(GuIn* in, GuPool* pool, GuPool* tmp_pool, GuExn* err)
|
||||||
|
{
|
||||||
|
PgfExprParser* parser = gu_new(PgfExprParser, tmp_pool);
|
||||||
|
parser->err = err;
|
||||||
|
parser->in = in;
|
||||||
|
parser->expr_pool = pool;
|
||||||
|
parser->tmp_pool = tmp_pool;
|
||||||
|
parser->ch = ' ';
|
||||||
|
pgf_expr_parser_token(parser);
|
||||||
|
return parser;
|
||||||
|
}
|
||||||
|
|
||||||
PgfExpr
|
PgfExpr
|
||||||
pgf_read_expr(GuIn* in, GuPool* pool, GuExn* err)
|
pgf_read_expr(GuIn* in, GuPool* pool, GuExn* err)
|
||||||
{
|
{
|
||||||
GuPool* tmp_pool = gu_new_pool();
|
GuPool* tmp_pool = gu_new_pool();
|
||||||
PgfExprParser* parser = gu_new(PgfExprParser, tmp_pool);
|
PgfExprParser* parser =
|
||||||
parser->err = err;
|
pgf_new_parser(in, pool, tmp_pool, err);
|
||||||
parser->in = in;
|
|
||||||
parser->expr_pool = pool;
|
|
||||||
parser->tmp_pool = NULL;
|
|
||||||
parser->ch = ' ';
|
|
||||||
pgf_expr_parser_token(parser);
|
|
||||||
PgfExpr expr = pgf_expr_parser_expr(parser);
|
PgfExpr expr = pgf_expr_parser_expr(parser);
|
||||||
|
if (parser->token_tag != PGF_TOKEN_EOF)
|
||||||
|
return gu_null_variant;
|
||||||
gu_pool_free(tmp_pool);
|
gu_pool_free(tmp_pool);
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PgfType*
|
||||||
|
pgf_read_type(GuIn* in, GuPool* pool, GuExn* err)
|
||||||
|
{
|
||||||
|
GuPool* tmp_pool = gu_new_pool();
|
||||||
|
PgfExprParser* parser =
|
||||||
|
pgf_new_parser(in, pool, tmp_pool, err);
|
||||||
|
PgfType* type = pgf_expr_parser_type(parser);
|
||||||
|
if (parser->token_tag != PGF_TOKEN_EOF)
|
||||||
|
return NULL;
|
||||||
|
gu_pool_free(tmp_pool);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
pgf_literal_eq(PgfLiteral lit1, PgfLiteral lit2)
|
pgf_literal_eq(PgfLiteral lit1, PgfLiteral lit2)
|
||||||
{
|
{
|
||||||
@@ -470,14 +859,56 @@ pgf_print_literal(PgfLiteral lit,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pgf_print_expr(PgfExpr expr, int prec,
|
pgf_print_expr(PgfExpr expr, PgfPrintContext* ctxt, int prec,
|
||||||
GuWriter* wtr, GuExn* err)
|
GuWriter* wtr, GuExn* err)
|
||||||
{
|
{
|
||||||
GuVariantInfo ei = gu_variant_open(expr);
|
GuVariantInfo ei = gu_variant_open(expr);
|
||||||
switch (ei.tag) {
|
switch (ei.tag) {
|
||||||
case PGF_EXPR_FUN: {
|
case PGF_EXPR_ABS: {
|
||||||
PgfExprFun* fun = ei.data;
|
PgfExprAbs* abs = ei.data;
|
||||||
gu_string_write(fun->fun, wtr, err);
|
|
||||||
|
if (prec > 1) {
|
||||||
|
gu_puts("(", wtr, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
gu_putc('\\', wtr, err);
|
||||||
|
|
||||||
|
PgfPrintContext* new_ctxt = ctxt;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (abs->bind_type == PGF_BIND_TYPE_IMPLICIT) {
|
||||||
|
gu_putc('{', wtr, err);
|
||||||
|
}
|
||||||
|
gu_string_write(abs->id, wtr, err);
|
||||||
|
if (abs->bind_type == PGF_BIND_TYPE_IMPLICIT) {
|
||||||
|
gu_putc('}', wtr, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
PgfPrintContext* c = malloc(sizeof(PgfPrintContext));
|
||||||
|
c->name = abs->id;
|
||||||
|
c->next = new_ctxt;
|
||||||
|
new_ctxt = c;
|
||||||
|
|
||||||
|
if (gu_variant_tag(abs->body) != PGF_EXPR_ABS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
gu_putc(',', wtr, err);
|
||||||
|
|
||||||
|
abs = gu_variant_data(abs->body);
|
||||||
|
}
|
||||||
|
|
||||||
|
gu_puts(" -> ", wtr, err);
|
||||||
|
pgf_print_expr(abs->body, new_ctxt, 1, wtr, err);
|
||||||
|
|
||||||
|
while (new_ctxt != ctxt) {
|
||||||
|
PgfPrintContext* next = new_ctxt->next;
|
||||||
|
free(new_ctxt);
|
||||||
|
new_ctxt = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prec > 1) {
|
||||||
|
gu_puts(")", wtr, err);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PGF_EXPR_APP: {
|
case PGF_EXPR_APP: {
|
||||||
@@ -485,9 +916,9 @@ pgf_print_expr(PgfExpr expr, int prec,
|
|||||||
if (prec > 3) {
|
if (prec > 3) {
|
||||||
gu_puts("(", wtr, err);
|
gu_puts("(", wtr, err);
|
||||||
}
|
}
|
||||||
pgf_print_expr(app->fun, 3, wtr, err);
|
pgf_print_expr(app->fun, ctxt, 3, wtr, err);
|
||||||
gu_puts(" ", wtr, err);
|
gu_puts(" ", wtr, err);
|
||||||
pgf_print_expr(app->arg, 4, wtr, err);
|
pgf_print_expr(app->arg, ctxt, 4, wtr, err);
|
||||||
if (prec > 3) {
|
if (prec > 3) {
|
||||||
gu_puts(")", wtr, err);
|
gu_puts(")", wtr, err);
|
||||||
}
|
}
|
||||||
@@ -501,25 +932,57 @@ pgf_print_expr(PgfExpr expr, int prec,
|
|||||||
case PGF_EXPR_META:
|
case PGF_EXPR_META:
|
||||||
gu_putc('?', wtr, err);
|
gu_putc('?', wtr, err);
|
||||||
break;
|
break;
|
||||||
case PGF_EXPR_ABS:
|
case PGF_EXPR_FUN: {
|
||||||
case PGF_EXPR_VAR:
|
PgfExprFun* fun = ei.data;
|
||||||
case PGF_EXPR_TYPED:
|
gu_string_write(fun->fun, wtr, err);
|
||||||
case PGF_EXPR_IMPL_ARG:
|
|
||||||
gu_impossible();
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
case PGF_EXPR_VAR: {
|
||||||
|
PgfExprVar* evar = ei.data;
|
||||||
|
|
||||||
|
int var = evar->var;
|
||||||
|
PgfPrintContext* c = ctxt;
|
||||||
|
while (c != NULL && var > 0) {
|
||||||
|
c = ctxt->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == NULL) {
|
||||||
|
gu_printf(wtr, err, "#%d", evar->var);
|
||||||
|
} else {
|
||||||
|
gu_string_write(c->name, wtr, err);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PGF_EXPR_TYPED: {
|
||||||
|
PgfExprTyped* typed = ei.data;
|
||||||
|
gu_putc('<', wtr, err);
|
||||||
|
pgf_print_expr(typed->expr, ctxt, 0, wtr, err);
|
||||||
|
gu_puts(" : ", wtr, err);
|
||||||
|
pgf_print_type(typed->type, ctxt, 0, wtr, err);
|
||||||
|
gu_putc('>', wtr, err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PGF_EXPR_IMPL_ARG: {
|
||||||
|
PgfExprImplArg* impl = ei.data;
|
||||||
|
gu_putc('{', wtr, err);
|
||||||
|
pgf_print_expr(impl->expr, ctxt, 0, wtr, err);
|
||||||
|
gu_putc('}', wtr, err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
gu_impossible();
|
gu_impossible();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
PgfPrintContext*
|
||||||
pgf_print_hypo(PgfHypo *hypo, int prec, GuWriter *wtr, GuExn *err)
|
pgf_print_hypo(PgfHypo *hypo, PgfPrintContext* ctxt, int prec,
|
||||||
|
GuWriter *wtr, GuExn *err)
|
||||||
{
|
{
|
||||||
if (hypo->bindtype == PGF_BIND_TYPE_IMPLICIT) {
|
if (hypo->bind_type == PGF_BIND_TYPE_IMPLICIT) {
|
||||||
gu_puts("({", wtr, err);
|
gu_puts("({", wtr, err);
|
||||||
gu_string_write(hypo->cid, wtr, err);
|
gu_string_write(hypo->cid, wtr, err);
|
||||||
gu_puts("} : ", wtr, err);
|
gu_puts("} : ", wtr, err);
|
||||||
pgf_print_type(hypo->type, 0, wtr, err);
|
pgf_print_type(hypo->type, ctxt, 0, wtr, err);
|
||||||
gu_puts(")", wtr, err);
|
gu_puts(")", wtr, err);
|
||||||
} else {
|
} else {
|
||||||
GuPool* tmp_pool = gu_new_pool();
|
GuPool* tmp_pool = gu_new_pool();
|
||||||
@@ -529,27 +992,34 @@ pgf_print_hypo(PgfHypo *hypo, int prec, GuWriter *wtr, GuExn *err)
|
|||||||
gu_puts("(", wtr, err);
|
gu_puts("(", wtr, err);
|
||||||
gu_string_write(hypo->cid, wtr, err);
|
gu_string_write(hypo->cid, wtr, err);
|
||||||
gu_puts(" : ", wtr, err);
|
gu_puts(" : ", wtr, err);
|
||||||
pgf_print_type(hypo->type, 0, wtr, err);
|
pgf_print_type(hypo->type, ctxt, 0, wtr, err);
|
||||||
gu_puts(")", wtr, err);
|
gu_puts(")", wtr, err);
|
||||||
} else {
|
} else {
|
||||||
pgf_print_type(hypo->type, prec, wtr, err);
|
pgf_print_type(hypo->type, ctxt, prec, wtr, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
gu_pool_free(tmp_pool);
|
gu_pool_free(tmp_pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PgfPrintContext* new_ctxt = malloc(sizeof(PgfPrintContext));
|
||||||
|
new_ctxt->name = hypo->cid;
|
||||||
|
new_ctxt->next = ctxt;
|
||||||
|
return new_ctxt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pgf_print_type(PgfType *type, int prec, GuWriter *wtr, GuExn *err)
|
pgf_print_type(PgfType *type, PgfPrintContext* ctxt, int prec,
|
||||||
|
GuWriter *wtr, GuExn *err)
|
||||||
{
|
{
|
||||||
size_t n_hypos = gu_seq_length(type->hypos);
|
size_t n_hypos = gu_seq_length(type->hypos);
|
||||||
|
|
||||||
if (n_hypos > 0) {
|
if (n_hypos > 0) {
|
||||||
if (prec > 0) gu_putc('(', wtr, err);
|
if (prec > 0) gu_putc('(', wtr, err);
|
||||||
|
|
||||||
|
PgfPrintContext* new_ctxt = ctxt;
|
||||||
for (size_t i = 0; i < n_hypos; i++) {
|
for (size_t i = 0; i < n_hypos; i++) {
|
||||||
PgfHypo *hypo = gu_seq_index(type->hypos, PgfHypo, i);
|
PgfHypo *hypo = gu_seq_index(type->hypos, PgfHypo, i);
|
||||||
pgf_print_hypo(hypo, 1, wtr, err);
|
new_ctxt = pgf_print_hypo(hypo, new_ctxt, 1, wtr, err);
|
||||||
|
|
||||||
gu_puts(" -> ", wtr, err);
|
gu_puts(" -> ", wtr, err);
|
||||||
}
|
}
|
||||||
@@ -558,9 +1028,15 @@ pgf_print_type(PgfType *type, int prec, GuWriter *wtr, GuExn *err)
|
|||||||
|
|
||||||
for (size_t i = 0; i < type->n_exprs; i++) {
|
for (size_t i = 0; i < type->n_exprs; i++) {
|
||||||
gu_puts(" ", wtr, err);
|
gu_puts(" ", wtr, err);
|
||||||
pgf_print_expr(type->exprs[i], 4, wtr, err);
|
pgf_print_expr(type->exprs[i], new_ctxt, 4, wtr, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (new_ctxt != ctxt) {
|
||||||
|
PgfPrintContext* next = new_ctxt->next;
|
||||||
|
free(new_ctxt);
|
||||||
|
new_ctxt = next;
|
||||||
|
}
|
||||||
|
|
||||||
if (prec > 0) gu_putc(')', wtr, err);
|
if (prec > 0) gu_putc(')', wtr, err);
|
||||||
} else if (type->n_exprs > 0) {
|
} else if (type->n_exprs > 0) {
|
||||||
if (prec > 3) gu_putc('(', wtr, err);
|
if (prec > 3) gu_putc('(', wtr, err);
|
||||||
@@ -569,7 +1045,7 @@ pgf_print_type(PgfType *type, int prec, GuWriter *wtr, GuExn *err)
|
|||||||
|
|
||||||
for (size_t i = 0; i < type->n_exprs; i++) {
|
for (size_t i = 0; i < type->n_exprs; i++) {
|
||||||
gu_puts(" ", wtr, err);
|
gu_puts(" ", wtr, err);
|
||||||
pgf_print_expr(type->exprs[i], 4, wtr, err);
|
pgf_print_expr(type->exprs[i], ctxt, 4, wtr, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prec > 3) gu_putc(')', wtr, err);
|
if (prec > 3) gu_putc(')', wtr, err);
|
||||||
@@ -577,3 +1053,38 @@ pgf_print_type(PgfType *type, int prec, GuWriter *wtr, GuExn *err)
|
|||||||
gu_string_write(type->cid, wtr, err);
|
gu_string_write(type->cid, wtr, err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
pgf_type_eq(PgfType* t1, PgfType* t2)
|
||||||
|
{
|
||||||
|
if (gu_seq_length(t1->hypos) != gu_seq_length(t2->hypos))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
size_t n_hypos = gu_seq_length(t1->hypos);
|
||||||
|
for (size_t i = 0; i < n_hypos; i++) {
|
||||||
|
PgfHypo *hypo1 = gu_seq_index(t1->hypos, PgfHypo, i);
|
||||||
|
PgfHypo *hypo2 = gu_seq_index(t1->hypos, PgfHypo, i);
|
||||||
|
|
||||||
|
if (hypo1->bind_type != hypo2->bind_type)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!gu_string_eq(hypo1->cid, hypo2->cid))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!pgf_type_eq(hypo1->type, hypo2->type))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gu_string_eq(t1->cid, t2->cid))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (t1->n_exprs != t2->n_exprs)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < t1->n_exprs; i++) {
|
||||||
|
if (!pgf_expr_eq(t1->exprs[i], t2->exprs[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
struct PgfHypo {
|
struct PgfHypo {
|
||||||
PgfBindType bindtype;
|
PgfBindType bind_type;
|
||||||
|
|
||||||
PgfCId cid;
|
PgfCId cid;
|
||||||
/**< Locally scoped name for the parameter if dependent types
|
/**< Locally scoped name for the parameter if dependent types
|
||||||
@@ -87,7 +87,7 @@ typedef enum {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PgfBindType bind_type;
|
PgfBindType bind_type;
|
||||||
PgfCId id; //
|
PgfCId id;
|
||||||
PgfExpr body;
|
PgfExpr body;
|
||||||
} PgfExprAbs;
|
} PgfExprAbs;
|
||||||
|
|
||||||
@@ -154,22 +154,38 @@ pgf_expr_unapply(PgfExpr expr, GuPool* pool);
|
|||||||
PgfExpr
|
PgfExpr
|
||||||
pgf_read_expr(GuIn* in, GuPool* pool, GuExn* err);
|
pgf_read_expr(GuIn* in, GuPool* pool, GuExn* err);
|
||||||
|
|
||||||
|
PgfType*
|
||||||
|
pgf_read_type(GuIn* in, GuPool* pool, GuExn* err);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
pgf_literal_eq(PgfLiteral lit1, PgfLiteral lit2);
|
pgf_literal_eq(PgfLiteral lit1, PgfLiteral lit2);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
pgf_expr_eq(PgfExpr e1, PgfExpr e2);
|
pgf_expr_eq(PgfExpr e1, PgfExpr e2);
|
||||||
|
|
||||||
|
bool
|
||||||
|
pgf_type_eq(PgfType* t1, PgfType* t2);
|
||||||
|
|
||||||
|
typedef struct PgfPrintContext PgfPrintContext;
|
||||||
|
|
||||||
|
struct PgfPrintContext {
|
||||||
|
PgfCId name;
|
||||||
|
PgfPrintContext* next;
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
pgf_print_literal(PgfLiteral lit, GuWriter* wtr, GuExn* err);
|
pgf_print_literal(PgfLiteral lit, GuWriter* wtr, GuExn* err);
|
||||||
|
|
||||||
void
|
void
|
||||||
pgf_print_expr(PgfExpr expr, int prec, GuWriter* wtr, GuExn* err);
|
pgf_print_expr(PgfExpr expr, PgfPrintContext* ctxt, int prec,
|
||||||
|
GuWriter* wtr, GuExn* err);
|
||||||
|
|
||||||
|
PgfPrintContext*
|
||||||
|
pgf_print_hypo(PgfHypo *hypo, PgfPrintContext* ctxt, int prec,
|
||||||
|
GuWriter *wtr, GuExn *err);
|
||||||
|
|
||||||
void
|
void
|
||||||
pgf_print_hypo(PgfHypo *hypo, int prec, GuWriter *wtr, GuExn *err);
|
pgf_print_type(PgfType *type, PgfPrintContext* ctxt, int prec,
|
||||||
|
GuWriter *wtr, GuExn *err);
|
||||||
void
|
|
||||||
pgf_print_type(PgfType *type, int prec, GuWriter *wtr, GuExn *err);
|
|
||||||
|
|
||||||
#endif /* EXPR_H_ */
|
#endif /* EXPR_H_ */
|
||||||
|
|||||||
@@ -178,6 +178,17 @@ pgf_iter_functions_by_cat(PgfPGF* pgf, PgfCId catname,
|
|||||||
gu_map_iter(pgf->abstract.funs, &clo.fn, err);
|
gu_map_iter(pgf->abstract.funs, &clo.fn, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PgfType*
|
||||||
|
pgf_function_type(PgfPGF* pgf, PgfCId funname)
|
||||||
|
{
|
||||||
|
PgfAbsFun* absfun =
|
||||||
|
gu_map_get(pgf->abstract.funs, &funname, PgfAbsFun*);
|
||||||
|
if (absfun == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return absfun->type;
|
||||||
|
}
|
||||||
|
|
||||||
GuString
|
GuString
|
||||||
pgf_print_name(PgfConcr* concr, PgfCId id)
|
pgf_print_name(PgfConcr* concr, PgfCId id)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -107,6 +107,9 @@ void
|
|||||||
pgf_iter_functions_by_cat(PgfPGF* pgf, PgfCId catname,
|
pgf_iter_functions_by_cat(PgfPGF* pgf, PgfCId catname,
|
||||||
GuMapItor* fn, GuExn* err);
|
GuMapItor* fn, GuExn* err);
|
||||||
|
|
||||||
|
PgfType*
|
||||||
|
pgf_function_type(PgfPGF* pgf, PgfCId funname);
|
||||||
|
|
||||||
GuString
|
GuString
|
||||||
pgf_print_name(PgfConcr*, PgfCId id);
|
pgf_print_name(PgfConcr*, PgfCId id);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <pgf/data.h>
|
#include <pgf/data.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GuMapItor fn;
|
GuMapItor fn;
|
||||||
@@ -33,11 +34,18 @@ pgf_print_cat(GuMapItor* fn, const void* key, void* value,
|
|||||||
gu_puts(" cat ", wtr, err);
|
gu_puts(" cat ", wtr, err);
|
||||||
gu_string_write(name, wtr, err);
|
gu_string_write(name, wtr, err);
|
||||||
|
|
||||||
|
PgfPrintContext* ctxt = NULL;
|
||||||
size_t n_hypos = gu_seq_length(cat->context);
|
size_t n_hypos = gu_seq_length(cat->context);
|
||||||
for (size_t i = 0; i < n_hypos; i++) {
|
for (size_t i = 0; i < n_hypos; i++) {
|
||||||
PgfHypo* hypo = gu_seq_get(cat->context, PgfHypo*, i);
|
PgfHypo* hypo = gu_seq_index(cat->context, PgfHypo, i);
|
||||||
gu_putc(' ', wtr, err);
|
gu_putc(' ', wtr, err);
|
||||||
pgf_print_hypo(hypo, 4, wtr, err);
|
ctxt = pgf_print_hypo(hypo, ctxt, 4, wtr, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (ctxt != NULL) {
|
||||||
|
PgfPrintContext* next = ctxt->next;
|
||||||
|
free(ctxt);
|
||||||
|
ctxt = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
gu_printf(wtr, err, " ; -- %f\n",cat->meta_prob);
|
gu_printf(wtr, err, " ; -- %f\n",cat->meta_prob);
|
||||||
@@ -55,7 +63,7 @@ pgf_print_absfun(GuMapItor* fn, const void* key, void* value,
|
|||||||
gu_puts(gu_seq_is_null(fun->defns) ? " data " : " fun ", wtr, err);
|
gu_puts(gu_seq_is_null(fun->defns) ? " data " : " fun ", wtr, err);
|
||||||
gu_string_write(name, wtr, err);
|
gu_string_write(name, wtr, err);
|
||||||
gu_puts(" : ", wtr, err);
|
gu_puts(" : ", wtr, err);
|
||||||
pgf_print_type(fun->type, 0, wtr, err);
|
pgf_print_type(fun->type, NULL, 0, wtr, err);
|
||||||
gu_printf(wtr, err, " ; -- %f\n", fun->ep.prob);
|
gu_printf(wtr, err, " ; -- %f\n", fun->ep.prob);
|
||||||
}
|
}
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ pgf_read_flags(PgfReader* rdr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static PgfType*
|
static PgfType*
|
||||||
pgf_read_type(PgfReader* rdr);
|
pgf_read_type_(PgfReader* rdr);
|
||||||
|
|
||||||
static PgfExpr
|
static PgfExpr
|
||||||
pgf_read_expr_(PgfReader* rdr)
|
pgf_read_expr_(PgfReader* rdr)
|
||||||
@@ -269,7 +269,7 @@ pgf_read_expr_(PgfReader* rdr)
|
|||||||
&expr, rdr->opool);
|
&expr, rdr->opool);
|
||||||
etyped->expr = pgf_read_expr_(rdr);
|
etyped->expr = pgf_read_expr_(rdr);
|
||||||
gu_return_on_exn(rdr->err, gu_null_variant);
|
gu_return_on_exn(rdr->err, gu_null_variant);
|
||||||
etyped->type = pgf_read_type(rdr);
|
etyped->type = pgf_read_type_(rdr);
|
||||||
gu_return_on_exn(rdr->err, gu_null_variant);
|
gu_return_on_exn(rdr->err, gu_null_variant);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -292,34 +292,38 @@ pgf_read_expr_(PgfReader* rdr)
|
|||||||
static void
|
static void
|
||||||
pgf_read_hypo(PgfReader* rdr, PgfHypo* hypo)
|
pgf_read_hypo(PgfReader* rdr, PgfHypo* hypo)
|
||||||
{
|
{
|
||||||
hypo->bindtype = pgf_read_tag(rdr);
|
hypo->bind_type = pgf_read_tag(rdr);
|
||||||
gu_return_on_exn(rdr->err, );
|
gu_return_on_exn(rdr->err, );
|
||||||
|
|
||||||
hypo->cid = pgf_read_cid(rdr);
|
hypo->cid = pgf_read_cid(rdr);
|
||||||
gu_return_on_exn(rdr->err, );
|
gu_return_on_exn(rdr->err, );
|
||||||
|
|
||||||
hypo->type = pgf_read_type(rdr);
|
hypo->type = pgf_read_type_(rdr);
|
||||||
gu_return_on_exn(rdr->err, );
|
gu_return_on_exn(rdr->err, );
|
||||||
}
|
}
|
||||||
|
|
||||||
static PgfType*
|
static PgfType*
|
||||||
pgf_read_type(PgfReader* rdr)
|
pgf_read_type_(PgfReader* rdr)
|
||||||
{
|
{
|
||||||
PgfType* type = gu_new(PgfType, rdr->opool);
|
|
||||||
|
|
||||||
size_t n_hypos = pgf_read_len(rdr);
|
size_t n_hypos = pgf_read_len(rdr);
|
||||||
gu_return_on_exn(rdr->err, NULL);
|
gu_return_on_exn(rdr->err, NULL);
|
||||||
type->hypos = gu_new_seq(PgfHypo, n_hypos, rdr->opool);
|
GuSeq hypos = gu_new_seq(PgfHypo, n_hypos, rdr->opool);
|
||||||
for (size_t i = 0; i < n_hypos; i++) {
|
for (size_t i = 0; i < n_hypos; i++) {
|
||||||
PgfHypo* hypo = gu_seq_index(type->hypos, PgfHypo, i);
|
PgfHypo* hypo = gu_seq_index(hypos, PgfHypo, i);
|
||||||
pgf_read_hypo(rdr, hypo);
|
pgf_read_hypo(rdr, hypo);
|
||||||
gu_return_on_exn(rdr->err, NULL);
|
gu_return_on_exn(rdr->err, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
type->cid = pgf_read_cid(rdr);
|
PgfCId cid = pgf_read_cid(rdr);
|
||||||
gu_return_on_exn(rdr->err, NULL);
|
gu_return_on_exn(rdr->err, NULL);
|
||||||
|
|
||||||
type->n_exprs = pgf_read_len(rdr);
|
size_t n_exprs = pgf_read_len(rdr);
|
||||||
|
|
||||||
|
PgfType* type = gu_new_flex(rdr->opool, PgfType, exprs, n_exprs);
|
||||||
|
type->hypos = hypos;
|
||||||
|
type->cid = cid;
|
||||||
|
type->n_exprs = n_exprs;
|
||||||
|
|
||||||
for (size_t i = 0; i < type->n_exprs; i++) {
|
for (size_t i = 0; i < type->n_exprs; i++) {
|
||||||
type->exprs[i] = pgf_read_expr_(rdr);
|
type->exprs[i] = pgf_read_expr_(rdr);
|
||||||
gu_return_on_exn(rdr->err, NULL);
|
gu_return_on_exn(rdr->err, NULL);
|
||||||
@@ -423,7 +427,7 @@ pgf_read_absfun(PgfReader* rdr)
|
|||||||
absfun->name = pgf_read_cid(rdr);
|
absfun->name = pgf_read_cid(rdr);
|
||||||
gu_return_on_exn(rdr->err, NULL);
|
gu_return_on_exn(rdr->err, NULL);
|
||||||
|
|
||||||
absfun->type = pgf_read_type(rdr);
|
absfun->type = pgf_read_type_(rdr);
|
||||||
gu_return_on_exn(rdr->err, NULL);
|
gu_return_on_exn(rdr->err, NULL);
|
||||||
|
|
||||||
absfun->arity = pgf_read_int(rdr);
|
absfun->arity = pgf_read_int(rdr);
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ int main(int argc, char* argv[]) {
|
|||||||
gu_printf(wtr, err, "%d (%.0f ms): ", ctr, 1000.0 * cpu_time_used);
|
gu_printf(wtr, err, "%d (%.0f ms): ", ctr, 1000.0 * cpu_time_used);
|
||||||
if (ep != NULL) {
|
if (ep != NULL) {
|
||||||
gu_printf(wtr, err, "[%.4f] (", ep->prob);
|
gu_printf(wtr, err, "[%.4f] (", ep->prob);
|
||||||
pgf_print_expr(ep->expr, 0, wtr, err);
|
pgf_print_expr(ep->expr, NULL, 0, wtr, err);
|
||||||
gu_printf(wtr, err, ")\n");
|
gu_printf(wtr, err, ")\n");
|
||||||
} else {
|
} else {
|
||||||
gu_printf(wtr, err, "---\n");
|
gu_printf(wtr, err, "---\n");
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ print_result(PgfExprProb* ep, PgfConcr* to_concr,
|
|||||||
{
|
{
|
||||||
// Write out the abstract syntax tree
|
// Write out the abstract syntax tree
|
||||||
gu_printf(wtr, err, " [%f] ", ep->prob);
|
gu_printf(wtr, err, " [%f] ", ep->prob);
|
||||||
pgf_print_expr(ep->expr, 0, wtr, err);
|
pgf_print_expr(ep->expr, NULL, 0, wtr, err);
|
||||||
gu_putc('\n', wtr, err);
|
gu_putc('\n', wtr, err);
|
||||||
|
|
||||||
// Enumerate the concrete syntax trees corresponding
|
// Enumerate the concrete syntax trees corresponding
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ Expr_repr(ExprObject *self)
|
|||||||
GuStringBuf* sbuf = gu_string_buf(tmp_pool);
|
GuStringBuf* sbuf = gu_string_buf(tmp_pool);
|
||||||
GuWriter* wtr = gu_string_buf_writer(sbuf);
|
GuWriter* wtr = gu_string_buf_writer(sbuf);
|
||||||
|
|
||||||
pgf_print_expr(self->expr, 0, wtr, err);
|
pgf_print_expr(self->expr, NULL, 0, wtr, err);
|
||||||
|
|
||||||
GuString str = gu_string_buf_freeze(sbuf, tmp_pool);
|
GuString str = gu_string_buf_freeze(sbuf, tmp_pool);
|
||||||
PyObject* pystr = gu2py_string(str);
|
PyObject* pystr = gu2py_string(str);
|
||||||
@@ -140,11 +140,11 @@ Expr_richcompare(ExprObject *e1, ExprObject *e2, int op)
|
|||||||
{
|
{
|
||||||
bool cmp = pgf_expr_eq(e1->expr,e2->expr);
|
bool cmp = pgf_expr_eq(e1->expr,e2->expr);
|
||||||
|
|
||||||
if (op == Py_EQ)
|
if (op == Py_EQ) {
|
||||||
return cmp ? Py_True : Py_False;
|
if (cmp) Py_RETURN_TRUE; else Py_RETURN_FALSE;
|
||||||
else if (op == Py_NE)
|
} else if (op == Py_NE) {
|
||||||
return cmp ? Py_False : Py_True;
|
if (cmp) Py_RETURN_FALSE; else Py_RETURN_TRUE;
|
||||||
else {
|
} else {
|
||||||
PyErr_SetString(PyExc_TypeError, "the operation is not supported");
|
PyErr_SetString(PyExc_TypeError, "the operation is not supported");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -157,6 +157,34 @@ static PyMethodDef Expr_methods[] = {
|
|||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static PyGetSetDef Expr_getseters[] = {
|
||||||
|
{"fun",
|
||||||
|
NULL, NULL,
|
||||||
|
"this the function in a function application",
|
||||||
|
NULL},
|
||||||
|
{"arg",
|
||||||
|
NULL, NULL,
|
||||||
|
"this the argument in a function application",
|
||||||
|
NULL},
|
||||||
|
{"val",
|
||||||
|
NULL, NULL,
|
||||||
|
"this is the value of a literal",
|
||||||
|
NULL},
|
||||||
|
{"id",
|
||||||
|
NULL, NULL,
|
||||||
|
"this is the id of a meta variable",
|
||||||
|
NULL},
|
||||||
|
{"name",
|
||||||
|
NULL, NULL,
|
||||||
|
"this is the name of a function",
|
||||||
|
NULL},
|
||||||
|
{"index",
|
||||||
|
NULL, NULL,
|
||||||
|
"this is the de Bruijn index of a variable",
|
||||||
|
NULL},
|
||||||
|
{NULL} /* Sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
static PyTypeObject pgf_ExprType = {
|
static PyTypeObject pgf_ExprType = {
|
||||||
PyObject_HEAD_INIT(NULL)
|
PyObject_HEAD_INIT(NULL)
|
||||||
0, /*ob_size*/
|
0, /*ob_size*/
|
||||||
@@ -188,7 +216,7 @@ static PyTypeObject pgf_ExprType = {
|
|||||||
0, /*tp_iternext */
|
0, /*tp_iternext */
|
||||||
Expr_methods, /*tp_methods */
|
Expr_methods, /*tp_methods */
|
||||||
0, /*tp_members */
|
0, /*tp_members */
|
||||||
0, /*tp_getset */
|
Expr_getseters, /*tp_getset */
|
||||||
0, /*tp_base */
|
0, /*tp_base */
|
||||||
0, /*tp_dict */
|
0, /*tp_dict */
|
||||||
0, /*tp_descr_get */
|
0, /*tp_descr_get */
|
||||||
@@ -297,6 +325,28 @@ Expr_unpack(ExprObject* self, PyObject *fargs)
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
GuVariantInfo i = gu_variant_open(expr);
|
GuVariantInfo i = gu_variant_open(expr);
|
||||||
switch (i.tag) {
|
switch (i.tag) {
|
||||||
|
case PGF_EXPR_ABS: {
|
||||||
|
PgfExprAbs* eabs = i.data;
|
||||||
|
|
||||||
|
ExprObject* py_body = (ExprObject*) pgf_ExprType.tp_alloc(&pgf_ExprType, 0);
|
||||||
|
if (py_body == NULL)
|
||||||
|
return NULL;
|
||||||
|
py_body->pool = NULL;
|
||||||
|
py_body->master = (self->master) ? self->master : (PyObject*) self;
|
||||||
|
py_body->expr = eabs->body;
|
||||||
|
Py_INCREF(py_body->master);
|
||||||
|
|
||||||
|
PyObject* py_bindtype =
|
||||||
|
(eabs->bind_type == PGF_BIND_TYPE_EXPLICIT) ? Py_True
|
||||||
|
: Py_False;
|
||||||
|
PyObject* py_var = gu2py_string(eabs->id);
|
||||||
|
PyObject* res =
|
||||||
|
Py_BuildValue("OOOO", py_bindtype, py_var, py_body, args);
|
||||||
|
Py_DECREF(py_var);
|
||||||
|
Py_DECREF(py_body);
|
||||||
|
Py_DECREF(args);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
case PGF_EXPR_APP: {
|
case PGF_EXPR_APP: {
|
||||||
PgfExprApp* eapp = i.data;
|
PgfExprApp* eapp = i.data;
|
||||||
|
|
||||||
@@ -355,6 +405,22 @@ Expr_unpack(ExprObject* self, PyObject *fargs)
|
|||||||
Py_DECREF(args);
|
Py_DECREF(args);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
case PGF_EXPR_VAR: {
|
||||||
|
PgfExprVar* evar = i.data;
|
||||||
|
PyObject* res = Py_BuildValue("iO", evar->var, args);
|
||||||
|
Py_DECREF(args);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
case PGF_EXPR_TYPED: {
|
||||||
|
PgfExprTyped* etyped = i.data;
|
||||||
|
expr = etyped->expr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PGF_EXPR_IMPL_ARG: {
|
||||||
|
PgfExprImplArg* eimpl = i.data;
|
||||||
|
expr = eimpl->expr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
gu_impossible();
|
gu_impossible();
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -367,7 +433,10 @@ static PyObject*
|
|||||||
Expr_getattro(ExprObject *self, PyObject *attr_name) {
|
Expr_getattro(ExprObject *self, PyObject *attr_name) {
|
||||||
const char* name = PyString_AsString(attr_name);
|
const char* name = PyString_AsString(attr_name);
|
||||||
|
|
||||||
GuVariantInfo i = gu_variant_open(self->expr);
|
PgfExpr expr = self->expr;
|
||||||
|
|
||||||
|
redo:;
|
||||||
|
GuVariantInfo i = gu_variant_open(expr);
|
||||||
switch (i.tag) {
|
switch (i.tag) {
|
||||||
case PGF_EXPR_APP: {
|
case PGF_EXPR_APP: {
|
||||||
PgfExprApp* eapp = i.data;
|
PgfExprApp* eapp = i.data;
|
||||||
@@ -419,13 +488,30 @@ Expr_getattro(ExprObject *self, PyObject *attr_name) {
|
|||||||
return PyInt_FromLong(emeta->id);
|
return PyInt_FromLong(emeta->id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PGF_EXPR_FUN: {
|
case PGF_EXPR_FUN: {
|
||||||
PgfExprFun* efun = i.data;
|
PgfExprFun* efun = i.data;
|
||||||
if (strcmp(name, "name") == 0) {
|
if (strcmp(name, "name") == 0) {
|
||||||
return gu2py_string(efun->fun);
|
return gu2py_string(efun->fun);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PGF_EXPR_VAR: {
|
||||||
|
PgfExprVar* evar = i.data;
|
||||||
|
if (strcmp(name, "index") == 0) {
|
||||||
|
return PyInt_FromLong(evar->var);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PGF_EXPR_TYPED: {
|
||||||
|
PgfExprTyped* etyped = i.data;
|
||||||
|
expr = etyped->expr;
|
||||||
|
goto redo;
|
||||||
|
}
|
||||||
|
case PGF_EXPR_IMPL_ARG: {
|
||||||
|
PgfExprImplArg* eimpl = i.data;
|
||||||
|
expr = eimpl->expr;
|
||||||
|
goto redo;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
gu_impossible();
|
gu_impossible();
|
||||||
}
|
}
|
||||||
@@ -433,6 +519,362 @@ Expr_getattro(ExprObject *self, PyObject *attr_name) {
|
|||||||
return PyObject_GenericGetAttr((PyObject*)self, attr_name);
|
return PyObject_GenericGetAttr((PyObject*)self, attr_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
PyObject* master;
|
||||||
|
GuPool* pool;
|
||||||
|
PgfType* type;
|
||||||
|
} TypeObject;
|
||||||
|
|
||||||
|
static PyTypeObject pgf_TypeType;
|
||||||
|
|
||||||
|
static TypeObject*
|
||||||
|
Type_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
|
{
|
||||||
|
TypeObject* self = (TypeObject *)type->tp_alloc(type, 0);
|
||||||
|
if (self != NULL) {
|
||||||
|
self->master = NULL;
|
||||||
|
self->pool = NULL;
|
||||||
|
self->type = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Type_dealloc(TypeObject* self)
|
||||||
|
{
|
||||||
|
if (self->master != NULL) {
|
||||||
|
Py_DECREF(self->master);
|
||||||
|
}
|
||||||
|
if (self->pool != NULL) {
|
||||||
|
gu_pool_free(self->pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
self->ob_type->tp_free((PyObject*)self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
Type_init(TypeObject *self, PyObject *args, PyObject *kwds)
|
||||||
|
{
|
||||||
|
PyObject* py_hypos;
|
||||||
|
const char* catname_s;
|
||||||
|
PyObject* py_exprs;
|
||||||
|
size_t n_exprs;
|
||||||
|
size_t n_hypos;
|
||||||
|
|
||||||
|
if (PyTuple_Size(args) == 1) {
|
||||||
|
py_hypos = NULL;
|
||||||
|
py_exprs = NULL;
|
||||||
|
n_exprs = 0;
|
||||||
|
n_hypos = 0;
|
||||||
|
if (!PyArg_ParseTuple(args, "s", &catname_s))
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
if (!PyArg_ParseTuple(args, "O!sO!",
|
||||||
|
&PyList_Type, &py_hypos,
|
||||||
|
&catname_s,
|
||||||
|
&PyList_Type, &py_exprs))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
n_exprs = PyList_Size(py_exprs);
|
||||||
|
n_hypos = PyList_Size(py_hypos);
|
||||||
|
}
|
||||||
|
|
||||||
|
self->pool = gu_new_pool();
|
||||||
|
self->master =
|
||||||
|
(n_exprs+n_hypos > 0) ? PyTuple_New(n_exprs+n_hypos) : NULL;
|
||||||
|
|
||||||
|
self->type = gu_new_flex(self->pool, PgfType, exprs, n_exprs);
|
||||||
|
|
||||||
|
self->type->hypos =
|
||||||
|
gu_new_seq(PgfHypo, n_hypos, self->pool);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n_hypos; i++) {
|
||||||
|
PyObject* obj = PyList_GetItem(py_hypos, i);
|
||||||
|
PyObject* py_bindtype;
|
||||||
|
PgfCId cid;
|
||||||
|
PyObject* py_type;
|
||||||
|
|
||||||
|
if (obj->ob_type == &pgf_TypeType) {
|
||||||
|
py_bindtype = Py_True;
|
||||||
|
cid = gu_str_string("_", self->pool);
|
||||||
|
py_type = obj;
|
||||||
|
} else {
|
||||||
|
if (!PyTuple_Check(obj) ||
|
||||||
|
PyTuple_GET_SIZE(obj) != 3) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "the arguments in the first list must be triples of (boolean,string,pgf.Type)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
py_bindtype = PyTuple_GetItem(obj, 0);
|
||||||
|
if (!PyBool_Check(py_bindtype)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "the arguments in the first list must be triples of (boolean,string,pgf.Type)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* py_var = PyTuple_GetItem(obj, 1);
|
||||||
|
if (!PyString_Check(py_var)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "the arguments in the first list must be triples of (boolean,string,pgf.Type)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cid = gu_str_string(PyString_AsString(py_var), self->pool);
|
||||||
|
|
||||||
|
py_type = PyTuple_GetItem(obj, 2);
|
||||||
|
if (py_type->ob_type != &pgf_TypeType) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "the arguments in the first list must be triples of (boolean,string,pgf.Type)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PgfHypo* hypo = gu_seq_index(self->type->hypos, PgfHypo, i);
|
||||||
|
hypo->bind_type =
|
||||||
|
(py_bindtype == Py_True) ? PGF_BIND_TYPE_EXPLICIT
|
||||||
|
: PGF_BIND_TYPE_IMPLICIT;
|
||||||
|
hypo->cid = cid;
|
||||||
|
hypo->type = ((TypeObject*) py_type)->type;
|
||||||
|
|
||||||
|
PyTuple_SetItem(self->master, i, py_type);
|
||||||
|
Py_INCREF(py_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
self->type->cid = gu_str_string(catname_s, self->pool);
|
||||||
|
|
||||||
|
self->type->n_exprs = n_exprs;
|
||||||
|
for (Py_ssize_t i = 0; i < n_exprs; i++) {
|
||||||
|
PyObject* obj = PyList_GetItem(py_exprs, i);
|
||||||
|
if (obj->ob_type != &pgf_ExprType) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "the arguments in the second list must be expressions");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyTuple_SetItem(self->master, n_hypos+i, obj);
|
||||||
|
Py_INCREF(obj);
|
||||||
|
|
||||||
|
self->type->exprs[i] = ((ExprObject*) obj)->expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
Type_repr(TypeObject *self)
|
||||||
|
{
|
||||||
|
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_print_type(self->type, NULL, 0, wtr, err);
|
||||||
|
|
||||||
|
GuString str = gu_string_buf_freeze(sbuf, tmp_pool);
|
||||||
|
PyObject* pystr = gu2py_string(str);
|
||||||
|
|
||||||
|
gu_pool_free(tmp_pool);
|
||||||
|
return pystr;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
Type_richcompare(TypeObject *t1, TypeObject *t2, int op)
|
||||||
|
{
|
||||||
|
bool cmp = pgf_type_eq(t1->type,t2->type);
|
||||||
|
|
||||||
|
if (op == Py_EQ) {
|
||||||
|
if (cmp) Py_RETURN_TRUE; else Py_RETURN_FALSE;
|
||||||
|
} else if (op == Py_NE) {
|
||||||
|
if (cmp) Py_RETURN_FALSE; else Py_RETURN_TRUE;
|
||||||
|
} else {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "the operation is not supported");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
Type_getHypos(TypeObject *self, void *closure)
|
||||||
|
{
|
||||||
|
PgfType* type = self->type;
|
||||||
|
|
||||||
|
PyObject* py_hypos = PyList_New(0);
|
||||||
|
if (py_hypos == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
size_t n_hypos = gu_seq_length(type->hypos);
|
||||||
|
for (size_t i = 0; i < n_hypos; i++) {
|
||||||
|
PgfHypo* hypo = gu_seq_index(type->hypos, PgfHypo, i);
|
||||||
|
|
||||||
|
PyObject* py_bindtype =
|
||||||
|
(hypo->bind_type == PGF_BIND_TYPE_EXPLICIT) ? Py_True
|
||||||
|
: Py_False;
|
||||||
|
|
||||||
|
PyObject* py_var = gu2py_string(hypo->cid);
|
||||||
|
if (py_var == NULL)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
TypeObject* py_type = (TypeObject*) pgf_TypeType.tp_alloc(&pgf_TypeType, 0);
|
||||||
|
if (py_type == NULL) {
|
||||||
|
Py_DECREF(py_var);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
py_type->pool = NULL;
|
||||||
|
py_type->master = (PyObject*) self;
|
||||||
|
py_type->type = hypo->type;
|
||||||
|
Py_INCREF(self);
|
||||||
|
|
||||||
|
PyObject* py_hypo =
|
||||||
|
Py_BuildValue("OOO", py_bindtype, py_var, py_type);
|
||||||
|
Py_DECREF(py_var);
|
||||||
|
Py_DECREF(py_type);
|
||||||
|
|
||||||
|
if (py_hypo == NULL)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (PyList_Append(py_hypos, (PyObject*) py_hypo) == -1)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
Py_DECREF(py_hypo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return py_hypos;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
Py_DECREF(py_hypos);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
Type_getCat(TypeObject *self, void *closure)
|
||||||
|
{
|
||||||
|
return gu2py_string(self->type->cid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
Type_getExprs(TypeObject *self, void *closure)
|
||||||
|
{
|
||||||
|
PgfType* type = self->type;
|
||||||
|
|
||||||
|
PyObject* py_exprs = PyList_New(0);
|
||||||
|
if (py_exprs == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < type->n_exprs; i++) {
|
||||||
|
ExprObject* py_expr =
|
||||||
|
(ExprObject*) pgf_ExprType.tp_alloc(&pgf_ExprType, 0);
|
||||||
|
if (py_expr == NULL)
|
||||||
|
goto fail;
|
||||||
|
py_expr->pool = NULL;
|
||||||
|
py_expr->master = (PyObject*) self;
|
||||||
|
py_expr->expr = type->exprs[i];
|
||||||
|
Py_INCREF(py_expr->master);
|
||||||
|
|
||||||
|
if (PyList_Append(py_exprs, (PyObject*) py_expr) == -1)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
Py_DECREF((PyObject*) py_expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return py_exprs;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
Py_DECREF(py_exprs);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
Type_unpack(TypeObject* self, PyObject *fargs)
|
||||||
|
{
|
||||||
|
PyObject* res = NULL;
|
||||||
|
PyObject* py_hypos = NULL;
|
||||||
|
PyObject* py_cat = NULL;
|
||||||
|
PyObject* py_exprs = NULL;
|
||||||
|
|
||||||
|
py_hypos = Type_getHypos(self, NULL);
|
||||||
|
if (py_hypos == NULL)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
py_cat = Type_getCat(self, NULL);
|
||||||
|
if (py_cat == NULL)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
py_exprs = Type_getExprs(self, NULL);
|
||||||
|
if (py_exprs == NULL)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
res = Py_BuildValue("OOO", py_hypos, py_cat, py_exprs);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
Py_XDECREF(py_hypos);
|
||||||
|
Py_XDECREF(py_cat);
|
||||||
|
Py_XDECREF(py_exprs);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyMethodDef Type_methods[] = {
|
||||||
|
{"unpack", (PyCFunction)Type_unpack, METH_VARARGS,
|
||||||
|
"Decomposes a type into its components"
|
||||||
|
},
|
||||||
|
{NULL} /* Sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyGetSetDef Type_getseters[] = {
|
||||||
|
{"hypos",
|
||||||
|
(getter)Type_getHypos, NULL,
|
||||||
|
"this is the list of hypotheses in the type signature",
|
||||||
|
NULL},
|
||||||
|
{"cat",
|
||||||
|
(getter)Type_getCat, NULL,
|
||||||
|
"this is the name of the category",
|
||||||
|
NULL},
|
||||||
|
{"exprs",
|
||||||
|
(getter)Type_getExprs, NULL,
|
||||||
|
"this is the list of indices for the category",
|
||||||
|
NULL},
|
||||||
|
{NULL} /* Sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyTypeObject pgf_TypeType = {
|
||||||
|
PyObject_HEAD_INIT(NULL)
|
||||||
|
0, /*ob_size*/
|
||||||
|
"pgf.Type", /*tp_name*/
|
||||||
|
sizeof(TypeObject), /*tp_basicsize*/
|
||||||
|
0, /*tp_itemsize*/
|
||||||
|
(destructor)Type_dealloc, /*tp_dealloc*/
|
||||||
|
0, /*tp_print*/
|
||||||
|
0, /*tp_getattr*/
|
||||||
|
0, /*tp_setattr*/
|
||||||
|
0, /*tp_compare*/
|
||||||
|
0, /*tp_repr*/
|
||||||
|
0, /*tp_as_number*/
|
||||||
|
0, /*tp_as_sequence*/
|
||||||
|
0, /*tp_as_mapping*/
|
||||||
|
0, /*tp_hash */
|
||||||
|
0, /*tp_call*/
|
||||||
|
(reprfunc) Type_repr, /*tp_str*/
|
||||||
|
0, /*tp_getattro*/
|
||||||
|
0, /*tp_setattro*/
|
||||||
|
0, /*tp_as_buffer*/
|
||||||
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
||||||
|
"abstract syntax type", /*tp_doc*/
|
||||||
|
0, /*tp_traverse */
|
||||||
|
0, /*tp_clear */
|
||||||
|
(richcmpfunc) Type_richcompare, /*tp_richcompare */
|
||||||
|
0, /*tp_weaklistoffset */
|
||||||
|
0, /*tp_iter */
|
||||||
|
0, /*tp_iternext */
|
||||||
|
Type_methods, /*tp_methods */
|
||||||
|
0, /*tp_members */
|
||||||
|
Type_getseters, /*tp_getset */
|
||||||
|
0, /*tp_base */
|
||||||
|
0, /*tp_dict */
|
||||||
|
0, /*tp_descr_get */
|
||||||
|
0, /*tp_descr_set */
|
||||||
|
0, /*tp_dictoffset */
|
||||||
|
(initproc)Type_init, /*tp_init */
|
||||||
|
0, /*tp_alloc */
|
||||||
|
(newfunc) Type_new, /*tp_new */
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct IterObject {
|
typedef struct IterObject {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
PGFObject* grammar;
|
PGFObject* grammar;
|
||||||
@@ -1504,6 +1946,37 @@ PGF_functionsByCat(PGFObject* self, PyObject *args)
|
|||||||
return functions;
|
return functions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static TypeObject*
|
||||||
|
PGF_functionType(PGFObject* self, PyObject *args)
|
||||||
|
{
|
||||||
|
const char *funname_s;
|
||||||
|
if (!PyArg_ParseTuple(args, "s", &funname_s))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
GuPool *tmp_pool = gu_local_pool();
|
||||||
|
GuString funname = gu_str_string(funname_s, tmp_pool);
|
||||||
|
|
||||||
|
PgfType* type =
|
||||||
|
pgf_function_type(self->pgf, funname);
|
||||||
|
|
||||||
|
gu_pool_free(tmp_pool);
|
||||||
|
|
||||||
|
if (type == NULL) {
|
||||||
|
PyErr_Format(PyExc_KeyError, "Function '%s' is not defined", funname_s);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeObject* pytype = (TypeObject*) pgf_TypeType.tp_alloc(&pgf_TypeType, 0);
|
||||||
|
if (pytype == NULL)
|
||||||
|
return NULL;
|
||||||
|
pytype->pool = NULL;
|
||||||
|
pytype->type = type;
|
||||||
|
pytype->master = (PyObject*) self;
|
||||||
|
Py_XINCREF(self);
|
||||||
|
|
||||||
|
return pytype;
|
||||||
|
}
|
||||||
|
|
||||||
static IterObject*
|
static IterObject*
|
||||||
PGF_generate(PGFObject* self, PyObject *args, PyObject *keywds)
|
PGF_generate(PGFObject* self, PyObject *args, PyObject *keywds)
|
||||||
{
|
{
|
||||||
@@ -1589,6 +2062,9 @@ static PyMethodDef PGF_methods[] = {
|
|||||||
{"functionsByCat", (PyCFunction)PGF_functionsByCat, METH_VARARGS,
|
{"functionsByCat", (PyCFunction)PGF_functionsByCat, METH_VARARGS,
|
||||||
"Returns the list of functions for a given category"
|
"Returns the list of functions for a given category"
|
||||||
},
|
},
|
||||||
|
{"functionType", (PyCFunction)PGF_functionType, METH_VARARGS,
|
||||||
|
"Returns the type of a function"
|
||||||
|
},
|
||||||
{"generate", (PyCFunction)PGF_generate, METH_VARARGS | METH_KEYWORDS,
|
{"generate", (PyCFunction)PGF_generate, METH_VARARGS | METH_KEYWORDS,
|
||||||
"Generates abstract syntax trees of given category in decreasing probability order"
|
"Generates abstract syntax trees of given category in decreasing probability order"
|
||||||
},
|
},
|
||||||
@@ -1703,11 +2179,43 @@ pgf_readExpr(PyObject *self, PyObject *args) {
|
|||||||
return pyexpr;
|
return pyexpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static TypeObject*
|
||||||
|
pgf_readType(PyObject *self, PyObject *args) {
|
||||||
|
size_t len;
|
||||||
|
const uint8_t *buf;
|
||||||
|
if (!PyArg_ParseTuple(args, "s#", &buf, &len))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
TypeObject* pytype = (TypeObject*) pgf_TypeType.tp_alloc(&pgf_TypeType, 0);
|
||||||
|
if (pytype == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
GuPool* tmp_pool = gu_local_pool();
|
||||||
|
GuIn* in = gu_data_in(buf, len, tmp_pool);
|
||||||
|
GuExn* err = gu_new_exn(NULL, gu_kind(type), tmp_pool);
|
||||||
|
|
||||||
|
pytype->pool = gu_new_pool();
|
||||||
|
pytype->type = pgf_read_type(in, pytype->pool, err);
|
||||||
|
pytype->master = NULL;
|
||||||
|
|
||||||
|
if (!gu_ok(err) || pytype->type == NULL) {
|
||||||
|
PyErr_SetString(PGFError, "The type cannot be parsed");
|
||||||
|
Py_DECREF(pytype);
|
||||||
|
gu_pool_free(tmp_pool);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gu_pool_free(tmp_pool);
|
||||||
|
return pytype;
|
||||||
|
}
|
||||||
|
|
||||||
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 the memory"},
|
"Reads a PGF file in the memory"},
|
||||||
{"readExpr", (void*)pgf_readExpr, METH_VARARGS,
|
{"readExpr", (void*)pgf_readExpr, METH_VARARGS,
|
||||||
"Parses a string as an abstract tree"},
|
"Parses a string as an abstract tree"},
|
||||||
|
{"readType", (void*)pgf_readType, METH_VARARGS,
|
||||||
|
"Parses a string as an abstract type"},
|
||||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1728,6 +2236,9 @@ initpgf(void)
|
|||||||
if (PyType_Ready(&pgf_ExprType) < 0)
|
if (PyType_Ready(&pgf_ExprType) < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (PyType_Ready(&pgf_TypeType) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
if (PyType_Ready(&pgf_IterType) < 0)
|
if (PyType_Ready(&pgf_IterType) < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1748,6 +2259,9 @@ initpgf(void)
|
|||||||
PyModule_AddObject(m, "Expr", (PyObject *) &pgf_ExprType);
|
PyModule_AddObject(m, "Expr", (PyObject *) &pgf_ExprType);
|
||||||
Py_INCREF(&pgf_ExprType);
|
Py_INCREF(&pgf_ExprType);
|
||||||
|
|
||||||
|
PyModule_AddObject(m, "Type", (PyObject *) &pgf_TypeType);
|
||||||
|
Py_INCREF(&pgf_TypeType);
|
||||||
|
|
||||||
Py_INCREF(&pgf_PGFType);
|
Py_INCREF(&pgf_PGFType);
|
||||||
Py_INCREF(&pgf_ConcrType);
|
Py_INCREF(&pgf_ConcrType);
|
||||||
Py_INCREF(&pgf_IterType);
|
Py_INCREF(&pgf_IterType);
|
||||||
|
|||||||
Reference in New Issue
Block a user