Add more parser tests
This commit is contained in:
parent
4908386435
commit
e3369d8a32
1 changed files with 540 additions and 14 deletions
|
|
@ -1,4 +1,8 @@
|
|||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "apfl.h"
|
||||
#include "resizable.h"
|
||||
|
||||
#include "test.h"
|
||||
|
||||
|
|
@ -102,10 +106,111 @@ new_helper(struct parser_test *pt, size_t size, void *data)
|
|||
return out;
|
||||
}
|
||||
|
||||
static struct apfl_expr_list_item
|
||||
list_item(bool expand, struct apfl_expr *expr)
|
||||
{
|
||||
return (struct apfl_expr_list_item) {
|
||||
.expand = expand,
|
||||
.expr = expr,
|
||||
};
|
||||
}
|
||||
|
||||
// Fugly macros to make it a bit easier to create a heap allocated struct value
|
||||
#define BEGIN_NEW(pt, T) ((T *)new_helper(pt, sizeof(T), &((T)
|
||||
#define END_NEW )))
|
||||
|
||||
enum listbuilder_cmd {
|
||||
LISTBUILDER_ADD,
|
||||
LISTBUILDER_STOP,
|
||||
};
|
||||
|
||||
#define LISTBUILDER_NAME(n) listbuilder_##n
|
||||
#define MKLISTBUILDER(name, listtype, itemtype, items_memb, len_memb) \
|
||||
listtype \
|
||||
LISTBUILDER_NAME(name)(struct parser_test *pt, ...) \
|
||||
{ \
|
||||
listtype body; \
|
||||
size_t cap = 0; \
|
||||
\
|
||||
apfl_resizable_init((void **)&body.items_memb, &body.len_memb, &cap); \
|
||||
\
|
||||
va_list ap; \
|
||||
va_start(ap, pt); \
|
||||
\
|
||||
for (;;) { \
|
||||
enum listbuilder_cmd cmd = va_arg(ap, enum listbuilder_cmd); \
|
||||
if (cmd == LISTBUILDER_STOP) { \
|
||||
break; \
|
||||
} \
|
||||
assert(cmd == LISTBUILDER_ADD); \
|
||||
itemtype item = va_arg(ap, itemtype); \
|
||||
\
|
||||
if (!apfl_resizable_append( \
|
||||
sizeof(itemtype), \
|
||||
(void **)&body.items_memb, \
|
||||
&body.len, \
|
||||
&cap, \
|
||||
&item, \
|
||||
1 \
|
||||
)) { \
|
||||
va_end(ap); \
|
||||
test_fatalf(pt->t, "Failed appending"); \
|
||||
assert(false); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
va_end(ap); \
|
||||
\
|
||||
return body; \
|
||||
} \
|
||||
|
||||
#define LIST_BEGIN(pt, builder) (LISTBUILDER_NAME(builder)(pt,
|
||||
#define LIST_END LISTBUILDER_STOP))
|
||||
#define LIST_ADD LISTBUILDER_ADD,
|
||||
|
||||
MKLISTBUILDER(list, struct apfl_expr_list, struct apfl_expr_list_item, items, len)
|
||||
MKLISTBUILDER(body, struct apfl_expr_body, struct apfl_expr, items, len)
|
||||
MKLISTBUILDER(dict, struct apfl_expr_dict, struct apfl_expr_dict_pair, items, len)
|
||||
MKLISTBUILDER(complex_func, struct apfl_expr_complex_func, struct apfl_expr_subfunc, subfuncs, len)
|
||||
MKLISTBUILDER(params, struct apfl_expr_params, struct apfl_expr_param, params, len)
|
||||
|
||||
#define POS(l, c) (struct apfl_position) { .line = l, .col = c }
|
||||
|
||||
static struct apfl_expr
|
||||
var(struct parser_test *pt, int line, int col, const char *v)
|
||||
{
|
||||
return (struct apfl_expr) {
|
||||
.type = APFL_EXPR_VAR,
|
||||
.position = POS(line, col),
|
||||
.var = new_string(pt, v),
|
||||
};
|
||||
}
|
||||
|
||||
struct apfl_expr *
|
||||
new_var(struct parser_test *pt, int line, int col, const char *v)
|
||||
{
|
||||
struct apfl_expr expr = var(pt, line, col, v);
|
||||
return new_helper(pt, sizeof(struct apfl_expr), &expr);
|
||||
}
|
||||
|
||||
static struct apfl_expr
|
||||
dot(struct parser_test *pt, int line, int col, const char *rhs, struct apfl_expr *lhs)
|
||||
{
|
||||
return (struct apfl_expr) {
|
||||
.type = APFL_EXPR_DOT,
|
||||
.position = POS(line, col),
|
||||
.dot.lhs = lhs,
|
||||
.dot.rhs = new_string(pt, rhs),
|
||||
};
|
||||
}
|
||||
|
||||
static struct apfl_expr *
|
||||
new_dot(struct parser_test *pt, int line, int col, const char *rhs, struct apfl_expr *lhs)
|
||||
{
|
||||
struct apfl_expr expr = dot(pt, line, col, rhs, lhs);
|
||||
return new_helper(pt, sizeof(struct apfl_expr), &expr);
|
||||
}
|
||||
|
||||
TEST(empty, t) {
|
||||
struct parser_test *pt = new_parser_test(t, "");
|
||||
expect_eof(pt);
|
||||
|
|
@ -116,28 +221,440 @@ TEST(hello_world, t) {
|
|||
struct parser_test *pt = new_parser_test(t, "print \"Hello World!\"");
|
||||
expect_expr(pt, (struct apfl_expr) {
|
||||
.type = APFL_EXPR_CALL,
|
||||
.position.line = 1,
|
||||
.position.col = 1,
|
||||
.position = POS(1, 1),
|
||||
.call = (struct apfl_expr_call) {
|
||||
.callee = BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_VAR,
|
||||
.position.line = 1,
|
||||
.position.col = 1,
|
||||
.var = new_string(pt, "print"),
|
||||
} END_NEW,
|
||||
.arguments = (struct apfl_expr_list) {
|
||||
.len = 1,
|
||||
.items = BEGIN_NEW(pt, struct apfl_expr_list_item) {
|
||||
.callee = new_var(pt, 1, 1, "print"),
|
||||
.arguments = LIST_BEGIN(pt, list)
|
||||
LIST_ADD (struct apfl_expr_list_item) {
|
||||
.expand = false,
|
||||
.expr = BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_CONSTANT,
|
||||
.position.line = 1,
|
||||
.position.col = 7,
|
||||
.position = POS(1, 7),
|
||||
.constant.type = APFL_EXPR_CONST_STRING,
|
||||
.constant.string = new_string(pt, "Hello World!"),
|
||||
} END_NEW,
|
||||
} END_NEW,
|
||||
},
|
||||
LIST_END,
|
||||
},
|
||||
});
|
||||
expect_eof(pt);
|
||||
destroy_parser_test(pt);
|
||||
}
|
||||
|
||||
TEST(empty_function, t) {
|
||||
struct parser_test *pt = new_parser_test(t, "{}");
|
||||
expect_expr(pt, (struct apfl_expr) {
|
||||
.type = APFL_EXPR_SIMPLE_FUNC,
|
||||
.position = POS(1, 1),
|
||||
.simple_func = LIST_BEGIN(pt, body)
|
||||
LIST_END,
|
||||
});
|
||||
expect_eof(pt);
|
||||
destroy_parser_test(pt);
|
||||
}
|
||||
|
||||
TEST(empty_list, t) {
|
||||
struct parser_test *pt = new_parser_test(t, "[]");
|
||||
expect_expr(pt, (struct apfl_expr) {
|
||||
.type = APFL_EXPR_LIST,
|
||||
.position = POS(1, 1),
|
||||
.list = LIST_BEGIN(pt, list)
|
||||
LIST_END,
|
||||
});
|
||||
expect_eof(pt);
|
||||
destroy_parser_test(pt);
|
||||
}
|
||||
|
||||
TEST(empty_dict, t) {
|
||||
struct parser_test *pt = new_parser_test(t, "[->]");
|
||||
expect_expr(pt, (struct apfl_expr) {
|
||||
.type = APFL_EXPR_DICT,
|
||||
.position = POS(1, 1),
|
||||
.dict = LIST_BEGIN(pt, dict)
|
||||
LIST_END,
|
||||
});
|
||||
expect_eof(pt);
|
||||
destroy_parser_test(pt);
|
||||
}
|
||||
|
||||
TEST(simple_dot_access, t) {
|
||||
struct parser_test *pt = new_parser_test(t, "foo.bar");
|
||||
expect_expr(pt, dot(pt, 1, 4, "bar", new_var(pt, 1, 1, "foo")));
|
||||
expect_eof(pt);
|
||||
destroy_parser_test(pt);
|
||||
}
|
||||
|
||||
TEST(simple_at_access, t) {
|
||||
struct parser_test *pt = new_parser_test(t, "foo@bar");
|
||||
expect_expr(pt, (struct apfl_expr) {
|
||||
.type = APFL_EXPR_AT,
|
||||
.position = POS(1, 4),
|
||||
.at.lhs = new_var(pt, 1, 1, "foo"),
|
||||
.at.rhs = new_var(pt, 1, 5, "bar"),
|
||||
});
|
||||
expect_eof(pt);
|
||||
destroy_parser_test(pt);
|
||||
}
|
||||
|
||||
TEST(parens, t) {
|
||||
// 1 2 3 4
|
||||
// 12345678901234567890123456789012345678901234567
|
||||
struct parser_test *pt = new_parser_test(t, "foo (bar baz) (aaa ~bbb (ccc) ~(ddd (eee fff)))");
|
||||
expect_expr(pt, (struct apfl_expr) {
|
||||
.type = APFL_EXPR_CALL,
|
||||
.position = POS(1, 1),
|
||||
.call = (struct apfl_expr_call) {
|
||||
.callee = new_var(pt, 1, 1, "foo"),
|
||||
.arguments = LIST_BEGIN(pt, list)
|
||||
LIST_ADD list_item(false, BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_CALL,
|
||||
.position = POS(1, 5),
|
||||
.call = (struct apfl_expr_call) {
|
||||
.callee = new_var(pt, 1, 6, "bar"),
|
||||
.arguments = LIST_BEGIN(pt, list)
|
||||
LIST_ADD list_item(false, new_var(pt, 1, 10, "baz")),
|
||||
LIST_END
|
||||
},
|
||||
} END_NEW),
|
||||
LIST_ADD list_item(false, BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_CALL,
|
||||
.position = POS(1, 15),
|
||||
.call = (struct apfl_expr_call) {
|
||||
.callee = new_var(pt, 1, 16, "aaa"),
|
||||
.arguments = LIST_BEGIN(pt, list)
|
||||
LIST_ADD list_item(true, new_var(pt, 1, 21, "bbb")),
|
||||
LIST_ADD list_item(false, BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_CALL,
|
||||
.position = POS(1, 25),
|
||||
.call = (struct apfl_expr_call) {
|
||||
.callee = new_var(pt, 1, 26, "ccc"),
|
||||
.arguments = LIST_BEGIN(pt, list)
|
||||
LIST_END,
|
||||
},
|
||||
} END_NEW),
|
||||
LIST_ADD list_item(true, BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_CALL,
|
||||
.position = POS(1, 32),
|
||||
.call = (struct apfl_expr_call) {
|
||||
.callee = new_var(pt, 1, 33, "ddd"),
|
||||
.arguments = LIST_BEGIN(pt, list)
|
||||
LIST_ADD list_item(false, BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_CALL,
|
||||
.position = POS(1, 37),
|
||||
.call = (struct apfl_expr_call) {
|
||||
.callee = new_var(pt, 1, 38, "eee"),
|
||||
.arguments = LIST_BEGIN(pt, list)
|
||||
LIST_ADD list_item(false, new_var(pt, 1, 42, "fff")),
|
||||
LIST_END,
|
||||
},
|
||||
} END_NEW),
|
||||
LIST_END,
|
||||
},
|
||||
} END_NEW),
|
||||
LIST_END,
|
||||
},
|
||||
} END_NEW),
|
||||
LIST_END,
|
||||
},
|
||||
});
|
||||
expect_eof(pt);
|
||||
destroy_parser_test(pt);
|
||||
}
|
||||
|
||||
TEST(complex_dot_at_access, t) {
|
||||
// 1 2
|
||||
// 123456789 01 23456789012345
|
||||
struct parser_test *pt = new_parser_test(t, "a@b.c@1@\"d\"@(e@(f.g h).i)");
|
||||
|
||||
expect_expr(pt, (struct apfl_expr) {
|
||||
.type = APFL_EXPR_AT,
|
||||
.position = POS(1, 12),
|
||||
.at = (struct apfl_expr_at) {
|
||||
.lhs = BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_AT,
|
||||
.position = POS(1, 8),
|
||||
.at = (struct apfl_expr_at) {
|
||||
.lhs = BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_AT,
|
||||
.position = POS(1, 6),
|
||||
.at = (struct apfl_expr_at) {
|
||||
.lhs = new_dot(pt, 1, 4, "c", BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_AT,
|
||||
.position = POS(1, 2),
|
||||
.at = (struct apfl_expr_at) {
|
||||
.lhs = new_var(pt, 1, 1, "a"),
|
||||
.rhs = new_var(pt, 1, 3, "b"),
|
||||
}
|
||||
} END_NEW),
|
||||
.rhs = BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_CONSTANT,
|
||||
.position = POS(1, 7),
|
||||
.constant.type = APFL_EXPR_CONST_NUMBER,
|
||||
.constant.number = 1,
|
||||
} END_NEW,
|
||||
},
|
||||
} END_NEW,
|
||||
.rhs = BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_CONSTANT,
|
||||
.position = POS(1, 9),
|
||||
.constant.type = APFL_EXPR_CONST_STRING,
|
||||
.constant.string = new_string(pt, "d"),
|
||||
} END_NEW,
|
||||
},
|
||||
} END_NEW,
|
||||
.rhs = BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_CALL,
|
||||
.position = POS(1, 13),
|
||||
.call = (struct apfl_expr_call) {
|
||||
.callee = new_dot(pt, 1, 23, "i", BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_AT,
|
||||
.position = POS(1, 15),
|
||||
.at = (struct apfl_expr_at) {
|
||||
.lhs = new_var(pt, 1, 14, "e"),
|
||||
.rhs = BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_CALL,
|
||||
.position = POS(1, 16),
|
||||
.call = (struct apfl_expr_call) {
|
||||
.callee = new_dot(pt, 1, 18, "g",
|
||||
new_var(pt, 1, 17, "f")
|
||||
),
|
||||
.arguments = LIST_BEGIN(pt, list)
|
||||
LIST_ADD (struct apfl_expr_list_item) {
|
||||
.expr = new_var(pt, 1, 21, "h"),
|
||||
.expand = false,
|
||||
},
|
||||
LIST_END,
|
||||
},
|
||||
} END_NEW,
|
||||
},
|
||||
} END_NEW),
|
||||
.arguments = LIST_BEGIN(pt, list)
|
||||
LIST_END,
|
||||
},
|
||||
} END_NEW,
|
||||
},
|
||||
});
|
||||
expect_eof(pt);
|
||||
destroy_parser_test(pt);
|
||||
}
|
||||
|
||||
TEST(factorial, t) {
|
||||
struct parser_test *pt = new_parser_test(t,
|
||||
// 1 2 3
|
||||
// 12345678901234567890123456789012
|
||||
"factorial := {\n"
|
||||
" 0 -> 1\n"
|
||||
" n -> * n (factorial (- n 1))\n"
|
||||
"}\n"
|
||||
"factorial 10"
|
||||
);
|
||||
|
||||
expect_expr(pt, (struct apfl_expr) {
|
||||
.type = APFL_EXPR_ASSIGNMENT,
|
||||
.position = POS(1, 11),
|
||||
.assignment = (struct apfl_expr_assignment) {
|
||||
.lhs = (struct apfl_expr_assignable) {
|
||||
.type = APFL_EXPR_ASSIGNABLE_VAR,
|
||||
.var = new_string(pt, "factorial"),
|
||||
},
|
||||
.rhs = BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_COMPLEX_FUNC,
|
||||
.position = POS(1, 14),
|
||||
.complex_func = LIST_BEGIN(pt, complex_func)
|
||||
LIST_ADD (struct apfl_expr_subfunc) {
|
||||
.params = LIST_BEGIN(pt, params)
|
||||
LIST_ADD (struct apfl_expr_param) {
|
||||
.type = APFL_EXPR_PARAM_CONSTANT,
|
||||
.constant = (struct apfl_expr_const) {
|
||||
.type = APFL_EXPR_CONST_NUMBER,
|
||||
.number = 0,
|
||||
},
|
||||
},
|
||||
LIST_END,
|
||||
.body = LIST_BEGIN(pt, body)
|
||||
LIST_ADD (struct apfl_expr) {
|
||||
.type = APFL_EXPR_CONSTANT,
|
||||
.position = POS(2, 10),
|
||||
.constant = (struct apfl_expr_const) {
|
||||
.type = APFL_EXPR_CONST_NUMBER,
|
||||
.number = 1,
|
||||
},
|
||||
},
|
||||
LIST_END
|
||||
},
|
||||
LIST_ADD (struct apfl_expr_subfunc) {
|
||||
.params = LIST_BEGIN(pt, params)
|
||||
LIST_ADD (struct apfl_expr_param) {
|
||||
.type = APFL_EXPR_PARAM_VAR,
|
||||
.var = new_string(pt, "n"),
|
||||
},
|
||||
LIST_END,
|
||||
.body = LIST_BEGIN(pt, body)
|
||||
LIST_ADD (struct apfl_expr) {
|
||||
.type = APFL_EXPR_CALL,
|
||||
.position = POS(3, 10),
|
||||
.call = (struct apfl_expr_call) {
|
||||
.callee = new_var(pt, 3, 10, "*"),
|
||||
.arguments = LIST_BEGIN(pt, list)
|
||||
LIST_ADD list_item(false, new_var(pt, 3, 12, "n")),
|
||||
LIST_ADD list_item(false, BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_CALL,
|
||||
.position = POS(3, 14),
|
||||
.call = (struct apfl_expr_call) {
|
||||
.callee = new_var(pt, 3, 15, "factorial"),
|
||||
.arguments = LIST_BEGIN(pt, list)
|
||||
LIST_ADD list_item(false, BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_CALL,
|
||||
.position = POS(3, 25),
|
||||
.call = (struct apfl_expr_call) {
|
||||
.callee = new_var(pt, 3, 26, "-"),
|
||||
.arguments = LIST_BEGIN(pt, list)
|
||||
LIST_ADD list_item(false, new_var(pt, 3, 28, "n")),
|
||||
LIST_ADD list_item(false, BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_CONSTANT,
|
||||
.position = POS(3, 30),
|
||||
.constant = (struct apfl_expr_const) {
|
||||
.type = APFL_EXPR_CONST_NUMBER,
|
||||
.number = 1,
|
||||
},
|
||||
} END_NEW),
|
||||
LIST_END,
|
||||
},
|
||||
} END_NEW),
|
||||
LIST_END,
|
||||
},
|
||||
|
||||
} END_NEW),
|
||||
LIST_END,
|
||||
},
|
||||
},
|
||||
LIST_END
|
||||
},
|
||||
LIST_END
|
||||
} END_NEW
|
||||
},
|
||||
});
|
||||
|
||||
expect_expr(pt, (struct apfl_expr) {
|
||||
.type = APFL_EXPR_CALL,
|
||||
.position = POS(5, 1),
|
||||
.call = (struct apfl_expr_call) {
|
||||
.callee = new_var(pt, 5, 1, "factorial"),
|
||||
.arguments = LIST_BEGIN(pt, list)
|
||||
LIST_ADD list_item(false, BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_CONSTANT,
|
||||
.position = POS(5, 11),
|
||||
.constant = (struct apfl_expr_const) {
|
||||
.type = APFL_EXPR_CONST_NUMBER,
|
||||
.number = 10,
|
||||
},
|
||||
} END_NEW),
|
||||
LIST_END,
|
||||
},
|
||||
});
|
||||
|
||||
expect_eof(pt);
|
||||
|
||||
destroy_parser_test(pt);
|
||||
}
|
||||
|
||||
TEST(map, t) {
|
||||
struct parser_test *pt = new_parser_test(t,
|
||||
// 123456789012345678901234
|
||||
"map := {\n"
|
||||
"_ [] -> []\n"
|
||||
"f [x ~xs] ->\n"
|
||||
" [(f x) ~(map f xs)]\n"
|
||||
"}\n"
|
||||
);
|
||||
expect_expr(pt, (struct apfl_expr) {
|
||||
.type = APFL_EXPR_ASSIGNMENT,
|
||||
.position = POS(1, 5),
|
||||
.assignment = (struct apfl_expr_assignment) {
|
||||
.lhs = (struct apfl_expr_assignable) {
|
||||
.type = APFL_EXPR_ASSIGNABLE_VAR,
|
||||
.var = new_string(pt, "map"),
|
||||
},
|
||||
.rhs = BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_COMPLEX_FUNC,
|
||||
.position = POS(1, 8),
|
||||
.complex_func = LIST_BEGIN(pt, complex_func)
|
||||
LIST_ADD (struct apfl_expr_subfunc) {
|
||||
.params = LIST_BEGIN(pt, params)
|
||||
LIST_ADD (struct apfl_expr_param) {
|
||||
.type = APFL_EXPR_PARAM_VAR,
|
||||
.var = new_string(pt, "_"),
|
||||
},
|
||||
LIST_ADD (struct apfl_expr_param) {
|
||||
.type = APFL_EXPR_PARAM_LIST,
|
||||
.list = LIST_BEGIN(pt, params)
|
||||
LIST_END,
|
||||
},
|
||||
LIST_END,
|
||||
.body = LIST_BEGIN(pt, body)
|
||||
LIST_ADD (struct apfl_expr) {
|
||||
.type = APFL_EXPR_LIST,
|
||||
.position = POS(2, 9),
|
||||
.list = LIST_BEGIN(pt, list)
|
||||
LIST_END,
|
||||
},
|
||||
LIST_END,
|
||||
},
|
||||
LIST_ADD (struct apfl_expr_subfunc) {
|
||||
.params = LIST_BEGIN(pt, params)
|
||||
LIST_ADD (struct apfl_expr_param) {
|
||||
.type = APFL_EXPR_PARAM_VAR,
|
||||
.var = new_string(pt, "f"),
|
||||
},
|
||||
LIST_ADD (struct apfl_expr_param) {
|
||||
.type = APFL_EXPR_PARAM_LIST,
|
||||
.list = LIST_BEGIN(pt, params)
|
||||
LIST_ADD (struct apfl_expr_param) {
|
||||
.type = APFL_EXPR_PARAM_VAR,
|
||||
.var = new_string(pt, "x"),
|
||||
},
|
||||
LIST_ADD (struct apfl_expr_param) {
|
||||
.type = APFL_EXPR_PARAM_EXPAND,
|
||||
.expand = BEGIN_NEW(pt, struct apfl_expr_param) {
|
||||
.type = APFL_EXPR_PARAM_VAR,
|
||||
.var = new_string(pt, "xs"),
|
||||
} END_NEW
|
||||
},
|
||||
LIST_END,
|
||||
},
|
||||
LIST_END,
|
||||
.body = LIST_BEGIN(pt, body)
|
||||
LIST_ADD (struct apfl_expr) {
|
||||
.type = APFL_EXPR_LIST,
|
||||
.position = POS(4, 5),
|
||||
.list = LIST_BEGIN(pt, list)
|
||||
LIST_ADD list_item(false, BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_CALL,
|
||||
.position = POS(4, 6),
|
||||
.call = (struct apfl_expr_call) {
|
||||
.callee = new_var(pt, 4, 7, "f"),
|
||||
.arguments = LIST_BEGIN(pt, list)
|
||||
LIST_ADD list_item(false, new_var(pt, 4, 9, "x")),
|
||||
LIST_END,
|
||||
},
|
||||
} END_NEW),
|
||||
LIST_ADD list_item(true, BEGIN_NEW(pt, struct apfl_expr) {
|
||||
.type = APFL_EXPR_CALL,
|
||||
.position = POS(4, 13),
|
||||
.call = (struct apfl_expr_call) {
|
||||
.callee = new_var(pt, 4, 14, "map"),
|
||||
.arguments = LIST_BEGIN(pt, list)
|
||||
LIST_ADD list_item(false, new_var(pt, 4, 18, "f")),
|
||||
LIST_ADD list_item(false, new_var(pt, 4, 20, "xs")),
|
||||
LIST_END
|
||||
},
|
||||
} END_NEW),
|
||||
LIST_END,
|
||||
},
|
||||
LIST_END
|
||||
},
|
||||
LIST_END,
|
||||
} END_NEW,
|
||||
},
|
||||
});
|
||||
expect_eof(pt);
|
||||
|
|
@ -147,4 +664,13 @@ TEST(hello_world, t) {
|
|||
TESTS_BEGIN
|
||||
ADDTEST(empty),
|
||||
ADDTEST(hello_world),
|
||||
ADDTEST(empty_function),
|
||||
ADDTEST(empty_list),
|
||||
ADDTEST(empty_dict),
|
||||
ADDTEST(simple_dot_access),
|
||||
ADDTEST(simple_at_access),
|
||||
ADDTEST(parens),
|
||||
ADDTEST(complex_dot_at_access),
|
||||
ADDTEST(factorial),
|
||||
ADDTEST(map),
|
||||
TESTS_END
|
||||
|
|
|
|||
Loading…
Reference in a new issue