summaryrefslogtreecommitdiff
path: root/src/runtime/c/pgf/expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/c/pgf/expr.c')
-rw-r--r--src/runtime/c/pgf/expr.c545
1 files changed, 395 insertions, 150 deletions
diff --git a/src/runtime/c/pgf/expr.c b/src/runtime/c/pgf/expr.c
index f9fcd1442..92e92f04f 100644
--- a/src/runtime/c/pgf/expr.c
+++ b/src/runtime/c/pgf/expr.c
@@ -224,20 +224,24 @@ typedef enum {
PGF_TOKEN_EOF,
} PGF_TOKEN_TAG;
+typedef GuUCS (*PgfParserGetc)(void* state, bool mark, GuExn* err);
+
struct PgfExprParser {
GuExn* err;
- GuIn* in;
GuPool* expr_pool;
GuPool* tmp_pool;
PGF_TOKEN_TAG token_tag;
GuStringBuf* token_value;
+
+ void* getch_state;
+ PgfParserGetc getch;
GuUCS ch;
};
static void
-pgf_expr_parser_getc(PgfExprParser* parser)
+pgf_expr_parser_getc(PgfExprParser* parser, bool mark)
{
- parser->ch = gu_in_utf8(parser->in, parser->err);
+ parser->ch = parser->getch(parser->getch_state, mark, parser->err);
if (!gu_ok(parser->err)) {
gu_exn_clear(parser->err);
parser->ch = EOF;
@@ -284,10 +288,11 @@ pgf_is_normal_ident(PgfCId id)
}
static void
-pgf_expr_parser_token(PgfExprParser* parser)
+pgf_expr_parser_token(PgfExprParser* parser, bool mark)
{
while (isspace(parser->ch)) {
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, mark);
+ mark = false;
}
parser->token_tag = PGF_TOKEN_UNKNOWN;
@@ -295,72 +300,73 @@ pgf_expr_parser_token(PgfExprParser* parser)
switch (parser->ch) {
case EOF:
+ pgf_expr_parser_getc(parser, mark);
parser->token_tag = PGF_TOKEN_EOF;
break;
case '(':
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, mark);
parser->token_tag = PGF_TOKEN_LPAR;
break;
case ')':
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, mark);
parser->token_tag = PGF_TOKEN_RPAR;
break;
case '{':
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, mark);
parser->token_tag = PGF_TOKEN_LCURLY;
break;
case '}':
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, mark);
parser->token_tag = PGF_TOKEN_RCURLY;
break;
case '<':
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, mark);
parser->token_tag = PGF_TOKEN_LTRIANGLE;
break;
case '>':
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, mark);
parser->token_tag = PGF_TOKEN_RTRIANGLE;
break;
case '?':
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, mark);
parser->token_tag = PGF_TOKEN_QUESTION;
break;
case '\\':
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, mark);
parser->token_tag = PGF_TOKEN_LAMBDA;
break;
case '-':
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, mark);
if (parser->ch == '>') {
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, false);
parser->token_tag = PGF_TOKEN_RARROW;
}
break;
case ',':
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, mark);
parser->token_tag = PGF_TOKEN_COMMA;
break;
case ':':
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, mark);
parser->token_tag = PGF_TOKEN_COLON;
break;
case ';':
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, mark);
parser->token_tag = PGF_TOKEN_SEMI;
break;
case '\'':
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, mark);
GuStringBuf* chars = gu_new_string_buf(parser->tmp_pool);
while (parser->ch != '\'' && parser->ch != EOF) {
if (parser->ch == '\\') {
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, false);
}
gu_out_utf8(parser->ch, gu_string_buf_out(chars), parser->err);
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, false);
}
if (parser->ch == '\'') {
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, false);
gu_out_utf8(0, gu_string_buf_out(chars), parser->err);
parser->token_tag = PGF_TOKEN_IDENT;
parser->token_value = chars;
@@ -372,7 +378,8 @@ pgf_expr_parser_token(PgfExprParser* parser)
if (pgf_is_ident_first(parser->ch)) {
do {
gu_out_utf8(parser->ch, gu_string_buf_out(chars), parser->err);
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, mark);
+ mark = false;
} while (pgf_is_ident_rest(parser->ch));
gu_out_utf8(0, gu_string_buf_out(chars), parser->err);
parser->token_tag = PGF_TOKEN_IDENT;
@@ -380,16 +387,17 @@ pgf_expr_parser_token(PgfExprParser* parser)
} else if (isdigit(parser->ch)) {
while (isdigit(parser->ch)) {
gu_out_utf8(parser->ch, gu_string_buf_out(chars), parser->err);
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, mark);
+ mark = false;
}
-
+
if (parser->ch == '.') {
gu_out_utf8(parser->ch, gu_string_buf_out(chars), parser->err);
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, false);
while (isdigit(parser->ch)) {
gu_out_utf8(parser->ch, gu_string_buf_out(chars), parser->err);
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, false);
}
gu_out_utf8(0, gu_string_buf_out(chars), parser->err);
parser->token_tag = PGF_TOKEN_FLT;
@@ -400,11 +408,11 @@ pgf_expr_parser_token(PgfExprParser* parser)
parser->token_value = chars;
}
} else if (parser->ch == '"') {
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, mark);
while (parser->ch != '"' && parser->ch != EOF) {
if (parser->ch == '\\') {
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, false);
switch (parser->ch) {
case '\\':
gu_out_utf8('\\', gu_string_buf_out(chars), parser->err);
@@ -430,15 +438,17 @@ pgf_expr_parser_token(PgfExprParser* parser)
} else {
gu_out_utf8(parser->ch, gu_string_buf_out(chars), parser->err);
}
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, false);
}
if (parser->ch == '"') {
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, false);
gu_out_utf8(0, gu_string_buf_out(chars), parser->err);
parser->token_tag = PGF_TOKEN_STR;
parser->token_value = chars;
}
+ } else {
+ pgf_expr_parser_getc(parser, mark);
}
break;
}
@@ -449,51 +459,51 @@ static bool
pgf_expr_parser_lookahead(PgfExprParser* parser, int ch)
{
while (isspace(parser->ch)) {
- pgf_expr_parser_getc(parser);
+ pgf_expr_parser_getc(parser, false);
}
-
+
return (parser->ch == ch);
}
-static PgfExpr
-pgf_expr_parser_expr(PgfExprParser* parser);
+PGF_API PgfExpr
+pgf_expr_parser_expr(PgfExprParser* parser, bool mark);
static PgfType*
-pgf_expr_parser_type(PgfExprParser* parser);
+pgf_expr_parser_type(PgfExprParser* parser, bool mark);
static PgfExpr
-pgf_expr_parser_term(PgfExprParser* parser)
+pgf_expr_parser_term(PgfExprParser* parser, bool mark)
{
switch (parser->token_tag) {
case PGF_TOKEN_LPAR: {
- pgf_expr_parser_token(parser);
- PgfExpr expr = pgf_expr_parser_expr(parser);
+ pgf_expr_parser_token(parser, false);
+ PgfExpr expr = pgf_expr_parser_expr(parser, false);
if (parser->token_tag == PGF_TOKEN_RPAR) {
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, mark);
return expr;
} else {
return gu_null_variant;
}
}
case PGF_TOKEN_LTRIANGLE: {
- pgf_expr_parser_token(parser);
- PgfExpr expr = pgf_expr_parser_expr(parser);
+ pgf_expr_parser_token(parser, false);
+ PgfExpr expr = pgf_expr_parser_expr(parser, false);
if (gu_variant_is_null(expr))
return gu_null_variant;
-
+
if (parser->token_tag != PGF_TOKEN_COLON) {
return gu_null_variant;
}
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
- PgfType* type = pgf_expr_parser_type(parser);
+ PgfType* type = pgf_expr_parser_type(parser, false);
if (type == NULL)
return gu_null_variant;
if (parser->token_tag != PGF_TOKEN_RTRIANGLE) {
return gu_null_variant;
}
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, mark);
return gu_new_variant_i(parser->expr_pool,
PGF_EXPR_TYPED,
@@ -501,14 +511,14 @@ pgf_expr_parser_term(PgfExprParser* parser)
expr, type);
}
case PGF_TOKEN_QUESTION: {
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, mark);
PgfMetaId id = 0;
if (parser->token_tag == PGF_TOKEN_INT) {
char* str =
gu_string_buf_data(parser->token_value);
id = atoi(str);
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, mark);
}
return gu_new_variant_i(parser->expr_pool,
PGF_EXPR_META,
@@ -517,7 +527,7 @@ pgf_expr_parser_term(PgfExprParser* parser)
}
case PGF_TOKEN_IDENT: {
PgfCId id = gu_string_buf_data(parser->token_value);
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, mark);
PgfExpr e;
PgfExprFun* fun =
gu_new_flex_variant(PGF_EXPR_FUN,
@@ -528,11 +538,11 @@ pgf_expr_parser_term(PgfExprParser* parser)
return e;
}
case PGF_TOKEN_INT: {
- char* str =
+ char* str =
gu_string_buf_data(parser->token_value);
int n = atoi(str);
- pgf_expr_parser_token(parser);
- PgfLiteral lit =
+ pgf_expr_parser_token(parser, mark);
+ PgfLiteral lit =
gu_new_variant_i(parser->expr_pool,
PGF_LITERAL_INT,
PgfLiteralInt,
@@ -545,7 +555,7 @@ pgf_expr_parser_term(PgfExprParser* parser)
case PGF_TOKEN_STR: {
char* str =
gu_string_buf_data(parser->token_value);
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, mark);
return pgf_expr_string(str, parser->expr_pool);
}
case PGF_TOKEN_FLT: {
@@ -554,8 +564,8 @@ pgf_expr_parser_term(PgfExprParser* parser)
double d;
if (!gu_string_to_double(str,&d))
return gu_null_variant;
- pgf_expr_parser_token(parser);
- PgfLiteral lit =
+ pgf_expr_parser_token(parser, mark);
+ PgfLiteral lit =
gu_new_variant_i(parser->expr_pool,
PGF_LITERAL_FLT,
PgfLiteralFlt,
@@ -571,29 +581,28 @@ pgf_expr_parser_term(PgfExprParser* parser)
}
static PgfExpr
-pgf_expr_parser_arg(PgfExprParser* parser)
+pgf_expr_parser_arg(PgfExprParser* parser, bool mark)
{
PgfExpr arg;
if (parser->token_tag == PGF_TOKEN_LCURLY) {
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
- arg = pgf_expr_parser_expr(parser);
+ arg = pgf_expr_parser_expr(parser, false);
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);
+ pgf_expr_parser_token(parser, mark);
arg = gu_new_variant_i(parser->expr_pool,
PGF_EXPR_IMPL_ARG,
PgfExprImplArg,
arg);
} else {
- arg = pgf_expr_parser_term(parser);
+ arg = pgf_expr_parser_term(parser, mark);
}
return arg;
@@ -607,17 +616,17 @@ pgf_expr_parser_bind(PgfExprParser* parser, GuBuf* binds)
if (parser->token_tag == PGF_TOKEN_LCURLY) {
bind_type = PGF_BIND_TYPE_IMPLICIT;
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
}
for (;;) {
if (parser->token_tag == PGF_TOKEN_IDENT) {
var =
gu_string_copy(gu_string_buf_data(parser->token_value), parser->expr_pool);
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
} else if (parser->token_tag == PGF_TOKEN_WILD) {
var = "_";
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
} else {
return false;
}
@@ -635,14 +644,14 @@ pgf_expr_parser_bind(PgfExprParser* parser, GuBuf* binds)
parser->token_tag != PGF_TOKEN_COMMA) {
break;
}
-
- pgf_expr_parser_token(parser);
+
+ pgf_expr_parser_token(parser, false);
}
if (bind_type == PGF_BIND_TYPE_IMPLICIT) {
if (parser->token_tag != PGF_TOKEN_RCURLY)
return false;
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
}
return true;
@@ -660,17 +669,17 @@ pgf_expr_parser_binds(PgfExprParser* parser)
if (parser->token_tag != PGF_TOKEN_COMMA)
break;
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
}
return binds;
}
-static PgfExpr
-pgf_expr_parser_expr(PgfExprParser* parser)
+PGF_API PgfExpr
+pgf_expr_parser_expr(PgfExprParser* parser, bool mark)
{
if (parser->token_tag == PGF_TOKEN_LAMBDA) {
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
GuBuf* binds = pgf_expr_parser_binds(parser);
if (binds == NULL)
return gu_null_variant;
@@ -678,9 +687,9 @@ pgf_expr_parser_expr(PgfExprParser* parser)
if (parser->token_tag != PGF_TOKEN_RARROW) {
return gu_null_variant;
}
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
- PgfExpr expr = pgf_expr_parser_expr(parser);
+ PgfExpr expr = pgf_expr_parser_expr(parser, mark);
if (gu_variant_is_null(expr))
return gu_null_variant;
@@ -691,10 +700,9 @@ pgf_expr_parser_expr(PgfExprParser* parser)
((PgfExprAbs*) gu_variant_data(bind))->body = expr;
expr = bind;
}
-
return expr;
} else {
- PgfExpr expr = pgf_expr_parser_term(parser);
+ PgfExpr expr = pgf_expr_parser_term(parser, mark);
if (gu_variant_is_null(expr))
return gu_null_variant;
@@ -704,17 +712,18 @@ pgf_expr_parser_expr(PgfExprParser* parser)
parser->token_tag != PGF_TOKEN_RTRIANGLE &&
parser->token_tag != PGF_TOKEN_COLON &&
parser->token_tag != PGF_TOKEN_COMMA &&
- parser->token_tag != PGF_TOKEN_SEMI) {
- PgfExpr arg = pgf_expr_parser_arg(parser);
+ parser->token_tag != PGF_TOKEN_SEMI &&
+ parser->token_tag != PGF_TOKEN_UNKNOWN) {
+ PgfExpr arg = pgf_expr_parser_arg(parser, mark);
if (gu_variant_is_null(arg))
- return gu_null_variant;
+ return expr;
expr = gu_new_variant_i(parser->expr_pool,
PGF_EXPR_APP,
PgfExprApp,
expr, arg);
}
-
+
return expr;
}
}
@@ -729,16 +738,16 @@ pgf_expr_parser_hypos(PgfExprParser* parser, GuBuf* hypos)
if (bind_type == PGF_BIND_TYPE_EXPLICIT &&
parser->token_tag == PGF_TOKEN_LCURLY) {
bind_type = PGF_BIND_TYPE_IMPLICIT;
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
}
if (parser->token_tag == PGF_TOKEN_IDENT) {
var =
gu_string_copy(gu_string_buf_data(parser->token_value), parser->expr_pool);
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
} else if (parser->token_tag == PGF_TOKEN_WILD) {
var = "_";
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
} else {
return false;
}
@@ -751,14 +760,14 @@ pgf_expr_parser_hypos(PgfExprParser* parser, GuBuf* hypos)
if (bind_type == PGF_BIND_TYPE_IMPLICIT &&
parser->token_tag == PGF_TOKEN_RCURLY) {
bind_type = PGF_BIND_TYPE_EXPLICIT;
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
}
if (parser->token_tag != PGF_TOKEN_COMMA) {
break;
}
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
}
if (bind_type == PGF_BIND_TYPE_IMPLICIT)
@@ -768,14 +777,14 @@ pgf_expr_parser_hypos(PgfExprParser* parser, GuBuf* hypos)
}
static PgfType*
-pgf_expr_parser_atom(PgfExprParser* parser)
+pgf_expr_parser_atom(PgfExprParser* parser, bool mark)
{
if (parser->token_tag != PGF_TOKEN_IDENT)
return NULL;
PgfCId cid =
gu_string_copy(gu_string_buf_data(parser->token_value), parser->expr_pool);
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, mark);
GuBuf* args = gu_new_buf(PgfExpr, parser->tmp_pool);
while (parser->token_tag != PGF_TOKEN_EOF &&
@@ -783,10 +792,10 @@ pgf_expr_parser_atom(PgfExprParser* parser)
parser->token_tag != PGF_TOKEN_RTRIANGLE &&
parser->token_tag != PGF_TOKEN_RARROW) {
PgfExpr arg =
- pgf_expr_parser_arg(parser);
+ pgf_expr_parser_arg(parser, mark);
if (gu_variant_is_null(arg))
- return NULL;
-
+ break;
+
gu_buf_push(args, PgfExpr, arg);
}
@@ -805,14 +814,14 @@ pgf_expr_parser_atom(PgfExprParser* parser)
}
static PgfType*
-pgf_expr_parser_type(PgfExprParser* parser)
+pgf_expr_parser_type(PgfExprParser* parser, bool mark)
{
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);
+ pgf_expr_parser_token(parser, false);
size_t n_start = gu_buf_length(hypos);
@@ -828,7 +837,7 @@ pgf_expr_parser_type(PgfExprParser* parser)
if (parser->token_tag != PGF_TOKEN_COLON)
return NULL;
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
} else {
PgfHypo* hypo = gu_buf_extend(hypos);
hypo->bind_type = PGF_BIND_TYPE_EXPLICIT;
@@ -838,33 +847,33 @@ pgf_expr_parser_type(PgfExprParser* parser)
size_t n_end = gu_buf_length(hypos);
- PgfType* type = pgf_expr_parser_type(parser);
+ PgfType* type = pgf_expr_parser_type(parser, false);
if (type == NULL)
return NULL;
if (parser->token_tag != PGF_TOKEN_RPAR)
return NULL;
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
if (parser->token_tag != PGF_TOKEN_RARROW)
return NULL;
- pgf_expr_parser_token(parser);
-
+ pgf_expr_parser_token(parser, false);
+
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);
+ type = pgf_expr_parser_atom(parser, mark);
if (type == NULL)
return NULL;
if (parser->token_tag != PGF_TOKEN_RARROW)
break;
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
PgfHypo* hypo = gu_buf_extend(hypos);
hypo->bind_type = PGF_BIND_TYPE_EXPLICIT;
@@ -878,29 +887,34 @@ pgf_expr_parser_type(PgfExprParser* parser)
return type;
}
-static PgfExprParser*
-pgf_new_parser(GuIn* in, GuPool* pool, GuPool* tmp_pool, GuExn* err)
+PGF_API PgfExprParser*
+pgf_new_parser(void* getc_state, PgfParserGetc getc, 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->getch_state = getc_state;
+ parser->getch = getc;
parser->ch = ' ';
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
return parser;
}
+static GuUCS
+pgf_expr_parser_in_getc(void* state, bool mark, GuExn* err)
+{
+ return gu_in_utf8((GuIn*) state, err);
+}
+
PGF_API PgfExpr
-pgf_read_expr(GuIn* in, GuPool* pool, GuExn* err)
+pgf_read_expr(GuIn* in, GuPool* pool, GuPool* tmp_pool, GuExn* err)
{
- GuPool* tmp_pool = gu_new_pool();
PgfExprParser* parser =
- pgf_new_parser(in, pool, tmp_pool, err);
- PgfExpr expr = pgf_expr_parser_expr(parser);
+ pgf_new_parser(in, pgf_expr_parser_in_getc, pool, tmp_pool, err);
+ PgfExpr expr = pgf_expr_parser_expr(parser, true);
if (parser->token_tag != PGF_TOKEN_EOF)
return gu_null_variant;
- gu_pool_free(tmp_pool);
return expr;
}
@@ -911,24 +925,24 @@ pgf_read_expr_tuple(GuIn* in,
{
GuPool* tmp_pool = gu_new_pool();
PgfExprParser* parser =
- pgf_new_parser(in, pool, tmp_pool, err);
+ pgf_new_parser(in, pgf_expr_parser_in_getc, pool, tmp_pool, err);
if (parser->token_tag != PGF_TOKEN_LTRIANGLE)
goto fail;
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
for (size_t i = 0; i < n_exprs; i++) {
if (i > 0) {
if (parser->token_tag != PGF_TOKEN_COMMA)
goto fail;
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
}
- exprs[i] = pgf_expr_parser_expr(parser);
+ exprs[i] = pgf_expr_parser_expr(parser, false);
if (gu_variant_is_null(exprs[i]))
goto fail;
}
if (parser->token_tag != PGF_TOKEN_RTRIANGLE)
goto fail;
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
if (parser->token_tag != PGF_TOKEN_EOF)
goto fail;
gu_pool_free(tmp_pool);
@@ -947,10 +961,10 @@ pgf_read_expr_matrix(GuIn* in,
{
GuPool* tmp_pool = gu_new_pool();
PgfExprParser* parser =
- pgf_new_parser(in, pool, tmp_pool, err);
+ pgf_new_parser(in, pgf_expr_parser_in_getc, pool, tmp_pool, err);
if (parser->token_tag != PGF_TOKEN_LTRIANGLE)
goto fail;
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
GuBuf* buf = gu_new_buf(PgfExpr, pool);
@@ -962,10 +976,10 @@ pgf_read_expr_matrix(GuIn* in,
if (i > 0) {
if (parser->token_tag != PGF_TOKEN_COMMA)
goto fail;
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
}
- exprs[i] = pgf_expr_parser_expr(parser);
+ exprs[i] = pgf_expr_parser_expr(parser, false);
if (gu_variant_is_null(exprs[i]))
goto fail;
}
@@ -973,14 +987,14 @@ pgf_read_expr_matrix(GuIn* in,
if (parser->token_tag != PGF_TOKEN_SEMI)
break;
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
}
if (parser->token_tag != PGF_TOKEN_RTRIANGLE)
goto fail;
}
- pgf_expr_parser_token(parser);
+ pgf_expr_parser_token(parser, false);
if (parser->token_tag != PGF_TOKEN_EOF)
goto fail;
gu_pool_free(tmp_pool);
@@ -993,15 +1007,13 @@ fail:
}
PGF_API PgfType*
-pgf_read_type(GuIn* in, GuPool* pool, GuExn* err)
+pgf_read_type(GuIn* in, GuPool* pool, GuPool* tmp_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);
+ pgf_new_parser(in, pgf_expr_parser_in_getc, pool, tmp_pool, err);
+ PgfType* type = pgf_expr_parser_type(parser, true);
if (parser->token_tag != PGF_TOKEN_EOF)
return NULL;
- gu_pool_free(tmp_pool);
return type;
}
@@ -1177,6 +1189,247 @@ pgf_expr_hash(GuHash h, PgfExpr e)
return h;
}
+PGF_API size_t
+pgf_expr_size(PgfExpr expr)
+{
+ GuVariantInfo ei = gu_variant_open(expr);
+ switch (ei.tag) {
+ case PGF_EXPR_ABS: {
+ PgfExprAbs* abs = ei.data;
+ return pgf_expr_size(abs->body);
+ }
+ case PGF_EXPR_APP: {
+ PgfExprApp* app = ei.data;
+ return pgf_expr_size(app->fun) + pgf_expr_size(app->arg);
+ }
+ case PGF_EXPR_LIT:
+ case PGF_EXPR_META:
+ case PGF_EXPR_FUN:
+ case PGF_EXPR_VAR: {
+ return 1;
+ }
+ case PGF_EXPR_TYPED: {
+ PgfExprTyped* typed = ei.data;
+ return pgf_expr_size(typed->expr);
+ }
+ case PGF_EXPR_IMPL_ARG: {
+ PgfExprImplArg* impl = ei.data;
+ return pgf_expr_size(impl->expr);
+ }
+ default:
+ gu_impossible();
+ return 0;
+ }
+}
+
+static void
+pgf_expr_functions_helper(PgfExpr expr, GuBuf* functions)
+{
+ GuVariantInfo ei = gu_variant_open(expr);
+ switch (ei.tag) {
+ case PGF_EXPR_ABS: {
+ PgfExprAbs* abs = ei.data;
+ pgf_expr_functions_helper(abs->body, functions);
+ break;
+ }
+ case PGF_EXPR_APP: {
+ PgfExprApp* app = ei.data;
+ pgf_expr_functions_helper(app->fun, functions);
+ pgf_expr_functions_helper(app->arg, functions);
+ break;
+ }
+ case PGF_EXPR_LIT:
+ case PGF_EXPR_META:
+ case PGF_EXPR_VAR: {
+ break;
+ }
+ case PGF_EXPR_FUN:{
+ PgfExprFun* fun = ei.data;
+ gu_buf_push(functions, GuString, fun->fun);
+ break;
+ }
+ case PGF_EXPR_TYPED: {
+ PgfExprTyped* typed = ei.data;
+ pgf_expr_functions_helper(typed->expr, functions);
+ break;
+ }
+ case PGF_EXPR_IMPL_ARG: {
+ PgfExprImplArg* impl = ei.data;
+ pgf_expr_functions_helper(impl->expr, functions);
+ break;
+ }
+ default:
+ gu_impossible();
+ }
+}
+
+PGF_API GuSeq*
+pgf_expr_functions(PgfExpr expr, GuPool* pool)
+{
+ GuBuf* functions = gu_new_buf(GuString, pool);
+ pgf_expr_functions_helper(expr, functions);
+ return gu_buf_data_seq(functions);
+}
+
+PGF_API PgfType*
+pgf_type_substitute(PgfType* type, GuSeq* meta_values, GuPool* pool)
+{
+ size_t n_hypos = gu_seq_length(type->hypos);
+ PgfHypos* new_hypos = gu_new_seq(PgfHypo, n_hypos, pool);
+ for (size_t i = 0; i < n_hypos; i++) {
+ PgfHypo* hypo = gu_seq_index(type->hypos, PgfHypo, i);
+ PgfHypo* new_hypo = gu_seq_index(new_hypos, PgfHypo, i);
+
+ new_hypo->bind_type = hypo->bind_type;
+ new_hypo->cid = gu_string_copy(hypo->cid, pool);
+ new_hypo->type = pgf_type_substitute(hypo->type, meta_values, pool);
+ }
+
+ PgfType *new_type =
+ gu_new_flex(pool, PgfType, exprs, type->n_exprs);
+ new_type->hypos = new_hypos;
+ new_type->cid = gu_string_copy(type->cid, pool);
+ new_type->n_exprs = type->n_exprs;
+
+ for (size_t i = 0; i < type->n_exprs; i++) {
+ new_type->exprs[i] =
+ pgf_expr_substitute(type->exprs[i], meta_values, pool);
+ }
+
+ return new_type;
+}
+
+PGF_API PgfExpr
+pgf_expr_substitute(PgfExpr expr, GuSeq* meta_values, GuPool* pool)
+{
+ GuVariantInfo ei = gu_variant_open(expr);
+ switch (ei.tag) {
+ case PGF_EXPR_ABS: {
+ PgfExprAbs* abs = ei.data;
+
+ PgfCId id = gu_string_copy(abs->id, pool);
+ PgfExpr body = pgf_expr_substitute(abs->body, meta_values, pool);
+ return gu_new_variant_i(pool,
+ PGF_EXPR_ABS,
+ PgfExprAbs,
+ abs->bind_type, id, body);
+ }
+ case PGF_EXPR_APP: {
+ PgfExprApp* app = ei.data;
+
+ PgfExpr fun = pgf_expr_substitute(app->fun, meta_values, pool);
+ PgfExpr arg = pgf_expr_substitute(app->arg, meta_values, pool);
+ return gu_new_variant_i(pool,
+ PGF_EXPR_APP,
+ PgfExprApp,
+ fun, arg);
+ }
+ case PGF_EXPR_LIT: {
+ PgfExprLit* elit = ei.data;
+
+ PgfLiteral lit;
+ GuVariantInfo i = gu_variant_open(elit->lit);
+ switch (i.tag) {
+ case PGF_LITERAL_STR: {
+ PgfLiteralStr* lstr = i.data;
+
+ PgfLiteralStr* new_lstr =
+ gu_new_flex_variant(PGF_LITERAL_STR,
+ PgfLiteralStr,
+ val, strlen(lstr->val)+1,
+ &lit, pool);
+ strcpy(new_lstr->val, lstr->val);
+ break;
+ }
+ case PGF_LITERAL_INT: {
+ PgfLiteralInt* lint = i.data;
+
+ PgfLiteralInt* new_lint =
+ gu_new_variant(PGF_LITERAL_INT,
+ PgfLiteralInt,
+ &lit, pool);
+ new_lint->val = lint->val;
+ break;
+ }
+ case PGF_LITERAL_FLT: {
+ PgfLiteralFlt* lflt = i.data;
+
+ PgfLiteralFlt* new_lflt =
+ gu_new_variant(PGF_LITERAL_FLT,
+ PgfLiteralFlt,
+ &lit, pool);
+ new_lflt->val = lflt->val;
+ break;
+ }
+ default:
+ gu_impossible();
+ }
+
+ return gu_new_variant_i(pool,
+ PGF_EXPR_LIT,
+ PgfExprLit,
+ lit);
+ }
+ case PGF_EXPR_META: {
+ PgfExprMeta* meta = ei.data;
+ PgfExpr e = gu_null_variant;
+ if ((size_t) meta->id < gu_seq_length(meta_values)) {
+ e = gu_seq_get(meta_values, PgfExpr, meta->id);
+ }
+ if (gu_variant_is_null(e)) {
+ e = gu_new_variant_i(pool,
+ PGF_EXPR_META,
+ PgfExprMeta,
+ meta->id);
+ }
+ return e;
+ }
+ case PGF_EXPR_FUN: {
+ PgfExprFun* fun = ei.data;
+
+ PgfExpr e;
+ PgfExprFun* new_fun =
+ gu_new_flex_variant(PGF_EXPR_FUN,
+ PgfExprFun,
+ fun, strlen(fun->fun)+1,
+ &e, pool);
+ strcpy(new_fun->fun, fun->fun);
+ return e;
+ }
+ case PGF_EXPR_VAR: {
+ PgfExprVar* var = ei.data;
+ return gu_new_variant_i(pool,
+ PGF_EXPR_VAR,
+ PgfExprVar,
+ var->var);
+ }
+ case PGF_EXPR_TYPED: {
+ PgfExprTyped* typed = ei.data;
+
+ PgfExpr expr = pgf_expr_substitute(typed->expr, meta_values, pool);
+ PgfType *type = pgf_type_substitute(typed->type, meta_values, pool);
+
+ return gu_new_variant_i(pool,
+ PGF_EXPR_TYPED,
+ PgfExprTyped,
+ expr,
+ type);
+ }
+ case PGF_EXPR_IMPL_ARG: {
+ PgfExprImplArg* impl = ei.data;
+
+ PgfExpr expr = pgf_expr_substitute(impl->expr, meta_values, pool);
+ return gu_new_variant_i(pool,
+ PGF_EXPR_IMPL_ARG,
+ PgfExprImplArg,
+ expr);
+ }
+ default:
+ gu_impossible();
+ return gu_null_variant;
+ }
+}
+
PGF_API void
pgf_print_cid(PgfCId id,
GuOut* out, GuExn* err)
@@ -1397,10 +1650,10 @@ pgf_print_hypo(PgfHypo *hypo, PgfPrintContext* ctxt, int prec,
} else {
pgf_print_type(hypo->type, ctxt, prec, out, err);
}
-
+
gu_pool_free(tmp_pool);
}
-
+
PgfPrintContext* new_ctxt = malloc(sizeof(PgfPrintContext));
new_ctxt->name = hypo->cid;
new_ctxt->next = ctxt;
@@ -1415,7 +1668,7 @@ pgf_print_type(PgfType *type, PgfPrintContext* ctxt, int prec,
if (n_hypos > 0) {
if (prec > 0) gu_putc('(', out, err);
-
+
PgfPrintContext* new_ctxt = ctxt;
for (size_t i = 0; i < n_hypos; i++) {
PgfHypo *hypo = gu_seq_index(type->hypos, PgfHypo, i);
@@ -1455,6 +1708,22 @@ pgf_print_type(PgfType *type, PgfPrintContext* ctxt, int prec,
}
PGF_API void
+pgf_print_context(PgfHypos *hypos, PgfPrintContext* ctxt,
+ GuOut *out, GuExn *err)
+{
+ PgfPrintContext* new_ctxt = ctxt;
+
+ size_t n_hypos = gu_seq_length(hypos);
+ for (size_t i = 0; i < n_hypos; i++) {
+ if (i > 0)
+ gu_putc(' ', out, err);
+
+ PgfHypo *hypo = gu_seq_index(hypos, PgfHypo, i);
+ new_ctxt = pgf_print_hypo(hypo, new_ctxt, 4, out, err);
+ }
+}
+
+PGF_API void
pgf_print_expr_tuple(size_t n_exprs, PgfExpr exprs[], PgfPrintContext* ctxt,
GuOut* out, GuExn* err)
{
@@ -1467,30 +1736,6 @@ pgf_print_expr_tuple(size_t n_exprs, PgfExpr exprs[], PgfPrintContext* ctxt,
gu_putc('>', out, err);
}
-PGF_API_DECL void
-pgf_print_category(PgfPGF *gr, PgfCId catname,
- GuOut* out, GuExn *err)
-{
- PgfAbsCat* abscat =
- gu_seq_binsearch(gr->abstract.cats, pgf_abscat_order, PgfAbsCat, catname);
- if (abscat == NULL) {
- GuExnData* exn = gu_raise(err, PgfExn);
- exn->data = "Unknown category";
- return;
- }
-
- gu_puts(abscat->name, out, err);
-
- PgfPrintContext* ctxt = NULL;
- size_t n_hypos = gu_seq_length(abscat->context);
- for (size_t i = 0; i < n_hypos; i++) {
- PgfHypo *hypo = gu_seq_index(abscat->context, PgfHypo, i);
-
- gu_putc(' ', out, err);
- ctxt = pgf_print_hypo(hypo, ctxt, 4, out, err);
- }
-}
-
PGF_API bool
pgf_type_eq(PgfType* t1, PgfType* t2)
{