~lbnz/xr0

cdae12b63299e0aa459123520ad84b5c8c66a2f0 — Xr0 Team 5 months ago b5d5bdf feat/program-1-complete
checkpoint
4 files changed, 136 insertions(+), 38 deletions(-)

M libx/string.h
M src/0v/ast/expr/expr.c
M src/0v/ast/expr/verify.c
M tests/3-program/100-lex/parse.x
M libx/string.h => libx/string.h +6 -0
@@ 11,4 11,10 @@ strncpy(char *dest, char *src, size_t n);
axiom size_t
strlen(char *s);

axiom int
strcmp(char *s1, char *s2);

axiom int
strncmp(char *s1, char *s2, size_t n);

#endif

M src/0v/ast/expr/expr.c => src/0v/ast/expr/expr.c +44 -5
@@ 58,6 58,49 @@ ast_expr_constant_create_char(char c)
	return expr;
}

static char *
escape_str(char c);

static void
ast_expr_constant_str_build(struct ast_expr *expr, struct strbuilder *b)
{
	int constant = expr->u.constant.constant;
	if (!expr->u.constant.ischar) {
		strbuilder_printf(b, "%d", constant);
		return;
	}
	switch (constant) {
	case '\n': case '\t': case '\v': case '\b': case '\f':
	case '\a': case '\\': case '\?': case '\'': case '\"':
	case '\0':
		strbuilder_printf(b, "%s", escape_str(constant));
		break;
	default:
		strbuilder_printf(b, "'%c'", constant);
		break;
	}
}

static char *
escape_str(char c)
{
	switch (c) { 
	case '\n': return "\\n";
	case '\t': return "\\t";
	case '\v': return "\\v";
	case '\b': return "\\b";
	case '\f': return "\\f";
	case '\a': return "\\a";
	case '\\': return "\\";
	case '\?': return "\?";
	case '\'': return "\'";
	case '\"': return "\"";
	/* TODO: handle octal and hex escapes */
	case '\0': return "\0";
	default: assert(false);
	}
}

int
ast_expr_as_constant(struct ast_expr *expr)
{


@@ 620,11 663,7 @@ ast_expr_str(struct ast_expr *expr)
		strbuilder_printf(b, expr->u.string);
		break;
	case EXPR_CONSTANT:
		if (expr->u.constant.ischar) {
			strbuilder_printf(b, "'%c'", expr->u.constant.constant);
		} else {
			strbuilder_printf(b, "%d", expr->u.constant.constant);
		}
		ast_expr_constant_str_build(expr, b);
		break;
	case EXPR_STRING_LITERAL:
		strbuilder_printf(b, "\"%s\"", expr->u.string);

M src/0v/ast/expr/verify.c => src/0v/ast/expr/verify.c +34 -20
@@ 185,22 185,23 @@ expr_unary_lvalue(struct ast_expr *expr, struct state *state)
struct lvalue *
expr_structmember_lvalue(struct ast_expr *expr, struct state *state)
{
	struct lvalue *root = ast_expr_lvalue(ast_expr_member_root(expr), state);
	struct object *root_obj = lvalue_object(root);
	struct ast_expr *root = ast_expr_member_root(expr);
	struct lvalue *root_lval = ast_expr_lvalue(root, state);
	struct object *root_obj = lvalue_object(root_lval);
	assert(root_obj);
	struct object *obj = object_getmember(
		root_obj,
		lvalue_type(root),
		ast_expr_member_field(expr),
		state
	char *field = ast_expr_member_field(expr);
	struct object *member = object_getmember(
		root_obj, lvalue_type(root_lval), field, state
	);
	if (!member) {
		/* TODO: lvalue error */
		return lvalue_create(NULL, NULL);
	}
	struct ast_type *t = object_getmembertype(
		root_obj,
		lvalue_type(root),
		ast_expr_member_field(expr),
		state
		root_obj, lvalue_type(root_lval), field, state
	);
	return lvalue_create(t, obj);
	assert(t);
	return lvalue_create(t, member);
}




@@ 383,17 384,24 @@ expr_unary_eval(struct ast_expr *expr, struct state *state)
static struct result *
expr_structmember_eval(struct ast_expr *expr, struct state *s)
{
	struct result *res = ast_expr_eval(ast_expr_member_root(expr), s);
	struct ast_expr *root = ast_expr_member_root(expr);
	struct result *res = ast_expr_eval(root, s);
	if (result_iserror(res)) {
		return res;
	}
	char *field = ast_expr_member_field(expr);
	struct object *member = value_struct_member(result_as_value(res), field);
	if (!member) {
		struct strbuilder *b = strbuilder_create();
		char *root_str = ast_expr_str(root);
		strbuilder_printf(
			b, "`%s' has no field `%s'", root_str, field
		);
		free(root_str);
		return result_error_create(error_create(strbuilder_build(b)));
	}
	struct value *obj_value = object_as_value(member);
	/* XXX */
	struct value *obj_value = object_as_value(
		value_struct_member(
			result_as_value(res),
			ast_expr_member_field(expr)
		)
	);
	struct value *v = obj_value ? value_copy(obj_value) : NULL;
	result_destroy(res);
	return result_value_create(v);


@@ 599,7 607,13 @@ expr_assign_eval(struct ast_expr *expr, struct state *state)
		return result_error_create(error_create(strbuilder_build(b)));
	}
	struct object *obj = lvalue_object(ast_expr_lvalue(lval, state));
	assert(obj);
	if (!obj) {
		struct strbuilder *b = strbuilder_create();
		char *s = ast_expr_str(lval);
		strbuilder_printf(b, "`%s' is not a valid object", s);
		free(s);
		return result_error_create(error_create(strbuilder_build(b)));
	}
	object_assign(obj, value_copy(result_as_value(res)));
	return res;
}

M tests/3-program/100-lex/parse.x => tests/3-program/100-lex/parse.x +52 -13
@@ 167,8 167,27 @@ struct defsresult {
	char *pos;
};

int
beginsdefs(char *s);

int
count_patterns(char *pos);

struct defsresult
parse_defs(char *pos);
parse_defs(char *input) ~ [
	if (beginsdefs(input)) {
		.alloc result.pre;
	}
	if (count_patterns(input)) {
		.alloc result.pattern;
	}
];

int
beginsdefs(char *s)
{
	return strncmp(s, "%{", 2) == 0;
}

struct rulesresult {
	struct token *token;


@@ 278,9 297,11 @@ struct stringresult {

struct stringresult
parse_defsraw(char *input) ~ [
	if (!(strncmp(input, "%{", 2) != 0)) {
	result.s = $;
	if (beginsdefs(input)) {
		.alloc result.s;
	}
	result.pos = $;
];

struct patternet {


@@ 290,18 311,39 @@ struct patternet {
};

struct patternet
parse_defsproper(char *pos) ~ [
parse_defsproper(char *input) ~ [
	result.pattern = $; /* TODO: put in else block */
	if (count_patterns(pos)) {
	if (count_patterns(input)) {
		.alloc result.pattern;
	}
	result.npat = $;
	result.pos = $;
];

struct defsresult
parse_defs(char *pos)
parse_defs(char *input)
{
	assert(false);
	struct stringresult raw;
	struct patternet set;
	struct defsresult res;

	input = skipws(input);
	if (*input == '\0') {
		puts("EOF in defs");
		exit(1);
	}
	raw = parse_defsraw(input);
	input = raw.pos;
	input = skipws(input);
	input = skipoptions(input);
	input = skipws(input);
	set = parse_defsproper(input);

	res.pre = raw.s;
	res.pattern = set.pattern;
	res.npat = set.npat;
	res.pos = set.pos;
	return res;
}

struct stringresult


@@ 310,7 352,7 @@ parse_defsraw(char *input)
	char *pos;
	struct stringresult res;

	if (strncmp(input, "%{", 2) != 0) {
	if (!beginsdefs(input)) {
		res.s = "";
		res.pos = input;
		return res;


@@ 353,9 395,6 @@ struct patternresult {
	char *pos;
};

int
count_patterns(char *pos);

struct patternpos {
	struct pattern *p;
	char *pos;


@@ 371,13 410,13 @@ parse_defs_n(char *pos, int npat) ~ [
];

struct patternet
parse_defsproper(char *pos)
parse_defsproper(char *input)
{
	struct patternet res;
	struct patternpos defs_n;

	res.npat = count_patterns(pos);
	defs_n = parse_defs_n(pos, res.npat);
	res.npat = count_patterns(input);
	defs_n = parse_defs_n(input, res.npat);
	res.pattern = defs_n.p;
	res.pos = defs_n.pos;
	return res;