harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit e46b94c395d0ccf2326ce00233e61649f1b5fc92
parent d256036430e8ad2aa3661dd53e21bacf8b32d8c4
Author: Drew DeVault <sir@cmpwn.com>
Date:   Thu, 31 Dec 2020 15:39:35 -0500

Pull line numbers into check

Diffstat:
Minclude/ast.h | 6++++++
Minclude/lex.h | 1+
Msrc/check.c | 111++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Msrc/parse.c | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
4 files changed, 151 insertions(+), 76 deletions(-)

diff --git a/include/ast.h b/include/ast.h @@ -5,6 +5,7 @@ #include "check.h" #include "expr.h" #include "identifier.h" +#include "lex.h" #include "types.h" enum ast_import_mode { @@ -14,6 +15,7 @@ enum ast_import_mode { }; struct ast_imports { + struct location loc; enum ast_import_mode mode; union { struct identifier ident; @@ -40,6 +42,7 @@ struct ast_enum_type { }; struct ast_function_parameters { + struct location loc; char *name; struct ast_type *type; struct ast_function_parameters *next; @@ -82,6 +85,7 @@ struct ast_struct_union_type { }; struct ast_type { + struct location loc; enum type_storage storage; unsigned int flags; union { @@ -235,6 +239,7 @@ struct ast_expression_unarithm { }; struct ast_expression { + struct location loc; enum expr_type type; union { struct ast_expression_access access; @@ -286,6 +291,7 @@ enum ast_decl_type { }; struct ast_decl { + struct location loc; enum ast_decl_type decl_type; bool exported; union { diff --git a/include/lex.h b/include/lex.h @@ -1,6 +1,7 @@ #ifndef HAREC_LEX_H #define HAREC_LEX_H #include <stdint.h> +#include <stdio.h> #include "types.h" // Keep sorted diff --git a/src/check.c b/src/check.c @@ -32,14 +32,14 @@ mkident(struct context *ctx, struct identifier *out, const struct identifier *in } static void -expect(bool constraint, char *fmt, ...) +expect(const struct location *loc, bool constraint, char *fmt, ...) { - // TODO: Bring along line numbers and such if (!constraint) { va_list ap; va_start(ap, fmt); - fprintf(stderr, "Error: "); + fprintf(stderr, "Error: %s:%d:%d: ", + loc->path, loc->lineno, loc->colno); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); abort(); @@ -64,7 +64,7 @@ check_expr_access(struct context *ctx, obj = scope_lookup(ctx->scope, &aexpr->access.ident); char buf[1024]; identifier_unparse_static(&aexpr->access.ident, buf, sizeof(buf)); - expect(obj, "Unknown object", buf); + expect(&aexpr->loc, obj, "Unknown object", buf); if (obj->otype == O_CONST) { // Lower constants *expr = *obj->value; @@ -80,10 +80,11 @@ check_expr_access(struct context *ctx, check_expression(ctx, aexpr->access.index, expr->access.index); const struct type *atype = expr->access.array->result; const struct type *itype = expr->access.index->result; - expect(atype->storage == TYPE_STORAGE_ARRAY - || atype->storage == TYPE_STORAGE_SLICE, + expect(&aexpr->access.array->loc, + atype->storage == TYPE_STORAGE_ARRAY || atype->storage == TYPE_STORAGE_SLICE, "Cannot index non-array, non-slice object"); - expect(type_is_integer(itype), "Cannot use non-integer type as slice/array index"); + expect(&aexpr->access.index->loc, type_is_integer(itype), + "Cannot use non-integer type as slice/array index"); expr->result = atype->array.members; break; case ACCESS_FIELD: @@ -103,7 +104,8 @@ check_expr_assert(struct context *ctx, if (aexpr->assert.cond != NULL) { expr->assert.cond = xcalloc(1, sizeof(struct expression)); check_expression(ctx, aexpr->assert.cond, expr->assert.cond); - expect(expr->assert.cond->result->storage == TYPE_STORAGE_BOOL, + expect(&aexpr->assert.cond->loc, + expr->assert.cond->result->storage == TYPE_STORAGE_BOOL, "Assertion condition must be boolean"); } else { expr->terminates = true; @@ -112,7 +114,8 @@ check_expr_assert(struct context *ctx, expr->assert.message = xcalloc(1, sizeof(struct expression)); if (aexpr->assert.message != NULL) { check_expression(ctx, aexpr->assert.message, expr->assert.message); - expect(expr->assert.message->result->storage == TYPE_STORAGE_STRING, + expect(&aexpr->assert.message->loc, + expr->assert.message->result->storage == TYPE_STORAGE_STRING, "Assertion message must be string"); } else { expr->assert.message->type = EXPR_CONSTANT; @@ -143,19 +146,24 @@ check_expr_assign(struct context *ctx, expr->assign.value = value; if (aexpr->assign.indirect) { - expect(object->result->storage == TYPE_STORAGE_POINTER, + expect(&aexpr->loc, + object->result->storage == TYPE_STORAGE_POINTER, "Cannot dereference non-pointer type for assignment"); - expect(!(object->result->pointer.flags & PTR_NULLABLE), + expect(&aexpr->loc, + !(object->result->pointer.flags & PTR_NULLABLE), "Cannot dereference nullable pointer type"); - expect(type_is_assignable(&ctx->store, + expect(&aexpr->loc, + type_is_assignable(&ctx->store, object->result->pointer.referent, value->result), "Value type is not assignable to pointer type"); } else { assert(object->type == EXPR_ACCESS); // Invariant const struct scope_object *obj = object->access.object; - expect(!(obj->type->flags & TYPE_CONST), "Cannot assign to const object"); - expect(type_is_assignable(&ctx->store, obj->type, value->result), + expect(&aexpr->loc, + !(obj->type->flags & TYPE_CONST), "Cannot assign to const object"); + expect(&aexpr->loc, + type_is_assignable(&ctx->store, obj->type, value->result), "rvalue type is not assignable to lvalue"); } } @@ -240,9 +248,11 @@ check_expr_binding(struct context *ctx, type = type_store_lookup_with_flags(&ctx->store, initializer->result, abinding->flags); } - expect(type->size != 0 && type->size != SIZE_UNDEFINED, + expect(&aexpr->loc, + type->size != 0 && type->size != SIZE_UNDEFINED, "Cannot create binding for type of zero or undefined size"); - expect(type_is_assignable(&ctx->store, type, initializer->result), + expect(&aexpr->loc, + type_is_assignable(&ctx->store, type, initializer->result), "Initializer is not assignable to binding type"); const struct scope_object *obj = scope_insert( @@ -273,7 +283,8 @@ check_expr_call(struct context *ctx, expr->call.lvalue = lvalue; const struct type *fntype = type_dereference(lvalue->result); - expect(fntype->storage == TYPE_STORAGE_FUNCTION, + expect(&aexpr->loc, + fntype->storage == TYPE_STORAGE_FUNCTION, "Cannot call non-function type"); expr->result = fntype->func.result; assert(fntype->func.variadism == VARIADISM_NONE); // TODO @@ -288,7 +299,8 @@ check_expr_call(struct context *ctx, arg->value = xcalloc(1, sizeof(struct expression)); check_expression(ctx, aarg->value, arg->value); - expect(type_is_assignable(&ctx->store, + expect(&aarg->value->loc, + type_is_assignable(&ctx->store, param->type, arg->value->result), "Argument is not assignable to parameter type"); @@ -298,8 +310,8 @@ check_expr_call(struct context *ctx, trleave(TR_CHECK, NULL); } - expect(!aarg, "Too many parameters for function call"); - expect(!param, "Not enough parameters for function call"); + expect(&aexpr->loc, !aarg, "Too many parameters for function call"); + expect(&aexpr->loc, !param, "Not enough parameters for function call"); trleave(TR_CHECK, NULL); } @@ -315,7 +327,9 @@ check_expr_cast(struct context *ctx, expr->cast.value = xcalloc(1, sizeof(struct expression)); check_expression(ctx, aexpr->cast.value, expr->cast.value); expr->result = type_store_lookup_atype(&ctx->store, aexpr->cast.type); - expect(type_is_castable(expr->result, expr->cast.value->result), "Invalid cast"); + expect(&aexpr->cast.type->loc, + type_is_castable(expr->result, expr->cast.value->result), + "Invalid cast"); } static void @@ -339,7 +353,7 @@ check_expr_array(struct context *ctx, type = value->result; } else { // TODO: Assignable? Requires spec update if so - expect(value->result == type, + expect(&item->value->loc, value->result == type, "Array members must be of a uniform type"); } @@ -442,7 +456,8 @@ check_expr_for(struct context *ctx, cond = xcalloc(1, sizeof(struct expression)); check_expression(ctx, aexpr->_for.cond, cond); expr->_for.cond = cond; - expect(cond->result->storage == TYPE_STORAGE_BOOL, + expect(&aexpr->_for.cond->loc, + cond->result->storage == TYPE_STORAGE_BOOL, "Expected for condition to be boolean"); if (aexpr->_for.afterthought) { @@ -486,7 +501,8 @@ check_expr_if(struct context *ctx, expr->result = &builtin_type_void; } - expect(cond->result->storage == TYPE_STORAGE_BOOL, + expect(&aexpr->_if.cond->loc, + cond->result->storage == TYPE_STORAGE_BOOL, "Expected if condition to be boolean"); expr->_if.cond = cond; @@ -546,11 +562,13 @@ check_expr_measure(struct context *ctx, expr->measure.value = xcalloc(1, sizeof(struct expression)); check_expression(ctx, aexpr->measure.value, expr->measure.value); enum type_storage vstor = expr->measure.value->result->storage; - expect(vstor == TYPE_STORAGE_ARRAY + expect(&aexpr->measure.value->loc, + vstor == TYPE_STORAGE_ARRAY || vstor == TYPE_STORAGE_SLICE || vstor == TYPE_STORAGE_STRING, "len argument must be of an array, slice, or str type"); - expect(expr->measure.value->result->size != SIZE_UNDEFINED, + expect(&aexpr->measure.value->loc, + expr->measure.value->result->size != SIZE_UNDEFINED, "Cannot take length of array type with undefined length"); break; case M_SIZE: @@ -576,8 +594,8 @@ check_expr_return(struct context *ctx, struct expression *rval = xcalloc(1, sizeof(struct expression)); check_expression(ctx, aexpr->_return.value, rval); expr->_return.value = rval; - expect(type_is_assignable(&ctx->store, - ctx->current_fntype->func.result, rval->result), + expect(&aexpr->_return.value->loc, + type_is_assignable(&ctx->store, ctx->current_fntype->func.result, rval->result), "Return value is not assignable to function result type"); } @@ -599,22 +617,27 @@ check_expr_unarithm(struct context *ctx, switch (expr->unarithm.op) { case UN_LNOT: - expect(operand->result->storage == TYPE_STORAGE_BOOL, + expect(&aexpr->unarithm.operand->loc, + operand->result->storage == TYPE_STORAGE_BOOL, "Cannot perform logical NOT (!) on non-boolean type"); expr->result = &builtin_type_bool; break; case UN_BNOT: - expect(type_is_integer(operand->result), + expect(&aexpr->unarithm.operand->loc, + type_is_integer(operand->result), "Cannot perform binary NOT (~) on non-integer type"); - expect(!type_is_signed(operand->result), + expect(&aexpr->unarithm.operand->loc, + !type_is_signed(operand->result), "Cannot perform binary NOT (~) on signed type"); expr->result = operand->result; break; case UN_MINUS: case UN_PLUS: - expect(type_is_numeric(operand->result), + expect(&aexpr->unarithm.operand->loc, + type_is_numeric(operand->result), "Cannot perform operation on non-numeric type"); - expect(type_is_signed(operand->result), + expect(&aexpr->unarithm.operand->loc, + type_is_signed(operand->result), "Cannot perform operation on unsigned type"); expr->result = operand->result; break; @@ -623,9 +646,11 @@ check_expr_unarithm(struct context *ctx, &ctx->store, operand->result, 0); break; case UN_DEREF: - expect(operand->result->storage == TYPE_STORAGE_POINTER, + expect(&aexpr->unarithm.operand->loc, + operand->result->storage == TYPE_STORAGE_POINTER, "Cannot de-reference non-pointer type"); - expect(!(operand->result->pointer.flags & PTR_NULLABLE), + expect(&aexpr->unarithm.operand->loc, + !(operand->result->pointer.flags & PTR_NULLABLE), "Cannot dereference nullable pointer type"); expr->result = operand->result->pointer.referent; break; @@ -734,6 +759,8 @@ check_function(struct context *ctx, decl->func.scope = scope_push(&ctx->scope, TR_CHECK); struct ast_function_parameters *params = afndecl->prototype.params; while (params) { + expect(&params->loc, params->name, + "Function parameters must be named"); struct identifier ident = { .name = params->name, }; @@ -747,7 +774,8 @@ check_function(struct context *ctx, check_expression(ctx, afndecl->body, body); decl->func.body = body; - expect(body->terminates || type_is_assignable(&ctx->store, fntype->func.result, body->result), + expect(&afndecl->body->loc, + body->terminates || type_is_assignable(&ctx->store, fntype->func.result, body->result), "Result value is not assignable to function result type"); // TODO: Add function name to errors @@ -755,9 +783,9 @@ check_function(struct context *ctx, || (decl->func.flags & FN_FINI) || (decl->func.flags & FN_TEST)) { const char *flags = "@flags"; // TODO: Unparse flags - expect(fntype->func.result == &builtin_type_void, + expect(&adecl->loc, fntype->func.result == &builtin_type_void, "%s function must return void", flags); - expect(!decl->exported, + expect(&adecl->loc, !decl->exported, "%s function cannot be exported", flags); } @@ -840,14 +868,15 @@ scan_const(struct context *ctx, const struct ast_global_decl *decl) check_expression(ctx, decl->init, initializer); // TODO: Lower implicit casts - expect(type_is_assignable(&ctx->store, type, initializer->result), - "Constnat type is not assignable from initializer type"); + expect(&decl->init->loc, type_is_assignable(&ctx->store, type, initializer->result), + "Constant type is not assignable from initializer type"); struct expression *value = xcalloc(1, sizeof(struct expression)); enum eval_result r = eval_expr(ctx, initializer, value); // TODO: More forward reference issues: - expect(r == EVAL_OK, "Unable to evaluate initializer at compile time"); + expect(&decl->init->loc, r == EVAL_OK, + "Unable to evaluate initializer at compile time"); struct identifier ident = {0}; mkident(ctx, &ident, &decl->ident); diff --git a/src/parse.c b/src/parse.c @@ -62,6 +62,37 @@ want(struct lexer *lexer, enum lexical_token ltok, struct token *tok) } } +static struct ast_expression * +mkexpr(const struct location *loc) +{ + struct ast_expression *exp = xcalloc(1, sizeof(struct ast_expression)); + exp->loc.lineno = loc->lineno; + exp->loc.colno = loc->colno; + exp->loc.path = strdup(loc->path); + return exp; +} + +static struct ast_type * +mktype(const struct location *loc) +{ + struct ast_type *t = xcalloc(1, sizeof(struct ast_type)); + t->loc.lineno = loc->lineno; + t->loc.colno = loc->colno; + t->loc.path = strdup(loc->path); + return t; +} + +static struct ast_function_parameters * +mkfuncparams(const struct location *loc) +{ + struct ast_function_parameters *p = + xcalloc(1, sizeof(struct ast_function_parameters)); + p->loc.lineno = loc->lineno; + p->loc.colno = loc->colno; + p->loc.path = strdup(loc->path); + return p; +} + void parse_identifier(struct lexer *lexer, struct identifier *ident) { @@ -158,13 +189,19 @@ parse_parameter_list(struct lexer *lexer, struct ast_function_type *type) trenter(TR_PARSE, "parameter-list"); struct token tok = {0}; bool more = true; - type->params = xcalloc(sizeof(struct ast_function_parameters), 1); + type->params = mkfuncparams(&lexer->loc); struct ast_function_parameters *next = type->params; while (more) { - want(lexer, T_NAME, &tok); - next->name = strdup(tok.name); - token_finish(&tok); - want(lexer, T_COLON, NULL); + switch (lex(lexer, &tok)) { + case T_NAME: + next->name = tok.name; + want(lexer, T_COLON, NULL); + break; + default: + unlex(lexer, &tok); + break; + } + next->type = parse_type(lexer); trace(TR_PARSE, "%s: [type]", next->name); switch (lex(lexer, &tok)) { @@ -180,8 +217,7 @@ parse_parameter_list(struct lexer *lexer, struct ast_function_type *type) break; default: unlex(lexer, &tok); - next->next = - xcalloc(sizeof(struct ast_function_parameters), 1); + next->next = mkfuncparams(&lexer->loc); next = next->next; break; } @@ -282,7 +318,7 @@ parse_primitive_type(struct lexer *lexer) { trenter(TR_PARSE, "primitive"); struct token tok = {0}; - struct ast_type *type = xcalloc(sizeof(struct ast_type), 1); + struct ast_type *type = mktype(&lexer->loc); switch (lex(lexer, &tok)) { case T_I8: case T_I16: @@ -338,7 +374,7 @@ parse_enum_type(struct lexer *lexer) { trenter(TR_PARSE, "enum"); struct token tok = {0}; - struct ast_type *type = xcalloc(sizeof(struct ast_type), 1); + struct ast_type *type = mktype(&lexer->loc); type->storage = TYPE_STORAGE_ENUM; struct ast_enum_field **next = &type->_enum.values; switch (lex(lexer, &tok)) { @@ -384,7 +420,7 @@ static struct ast_type * parse_struct_union_type(struct lexer *lexer) { struct token tok = {0}; - struct ast_type *type = xcalloc(sizeof(struct ast_type), 1); + struct ast_type *type = mktype(&lexer->loc); struct ast_struct_union_type *next = &type->struct_union; switch (lex(lexer, &tok)) { case T_STRUCT: @@ -466,7 +502,7 @@ static struct ast_type * parse_tagged_union_type(struct lexer *lexer) { trenter(TR_PARSE, "tagged union"); - struct ast_type *type = xcalloc(sizeof(struct ast_type), 1); + struct ast_type *type = mktype(&lexer->loc); type->storage = TYPE_STORAGE_TAGGED_UNION; struct ast_tagged_union_type *next = &type->tagged_union; next->type = parse_type(lexer); @@ -541,7 +577,7 @@ parse_type(struct lexer *lexer) trace(TR_PARSE, "nullable"); /* fallthrough */ case T_TIMES: - type = xcalloc(sizeof(struct ast_type), 1); + type = mktype(&lexer->loc); type->storage = TYPE_STORAGE_POINTER; type->pointer.referent = parse_type(lexer); if (nullable) { @@ -557,7 +593,7 @@ parse_type(struct lexer *lexer) type = parse_tagged_union_type(lexer); break; case T_LBRACKET: - type = xcalloc(sizeof(struct ast_type), 1); + type = mktype(&lexer->loc); switch (lex(lexer, &tok)) { case T_RBRACKET: type->storage = TYPE_STORAGE_SLICE; @@ -583,7 +619,7 @@ parse_type(struct lexer *lexer) want(lexer, T_FN, NULL); // fallthrough case T_FN: - type = xcalloc(sizeof(struct ast_type), 1); + type = mktype(&lexer->loc); type->storage = TYPE_STORAGE_FUNCTION; parse_prototype(lexer, &type->func); if (noreturn) { @@ -592,7 +628,7 @@ parse_type(struct lexer *lexer) break; case T_NAME: unlex(lexer, &tok); - type = xcalloc(sizeof(struct ast_type), 1); + type = mktype(&lexer->loc); type->storage = TYPE_STORAGE_ALIAS; parse_identifier(lexer, &type->alias); break; @@ -610,7 +646,7 @@ static struct ast_expression * parse_access(struct lexer *lexer, struct identifier ident) { trace(TR_PARSE, "access"); - struct ast_expression *exp = xcalloc(1, sizeof(struct ast_expression)); + struct ast_expression *exp = mkexpr(&lexer->loc); exp->type = EXPR_ACCESS; exp->access.type = ACCESS_IDENTIFIER; exp->access.ident = ident; @@ -622,7 +658,7 @@ parse_constant(struct lexer *lexer) { trenter(TR_PARSE, "constant"); - struct ast_expression *exp = xcalloc(1, sizeof(struct ast_expression)); + struct ast_expression *exp = mkexpr(&lexer->loc); exp->type = EXPR_CONSTANT; struct token tok = {0}; @@ -691,7 +727,7 @@ parse_array_literal(struct lexer *lexer) struct token tok; want(lexer, T_LBRACKET, &tok); - struct ast_expression *exp = xcalloc(1, sizeof(struct ast_expression)); + struct ast_expression *exp = mkexpr(&lexer->loc); exp->type = EXPR_CONSTANT; exp->constant.storage = TYPE_STORAGE_ARRAY; @@ -700,7 +736,7 @@ parse_array_literal(struct lexer *lexer) while (lex(lexer, &tok) != T_RBRACKET) { unlex(lexer, &tok); - item = *next = xcalloc(1, sizeof(struct ast_expression)); + item = *next = xcalloc(1, sizeof(struct ast_array_constant)); item->value = parse_simple_expression(lexer); next = &item->next; @@ -803,7 +839,7 @@ parse_struct_literal(struct lexer *lexer, struct identifier ident) { trenter(TR_PARSE, "struct-literal"); want(lexer, T_LBRACE, NULL); - struct ast_expression *exp = xcalloc(sizeof(struct ast_expression), 1); + struct ast_expression *exp = mkexpr(&lexer->loc); exp->type = EXPR_STRUCT; exp->_struct.type = ident; struct ast_field_value **next = &exp->_struct.fields; @@ -900,7 +936,7 @@ parse_assertion_expression(struct lexer *lexer) { trace(TR_PARSE, "assertion"); - struct ast_expression *exp = xcalloc(1, sizeof(struct ast_expression)); + struct ast_expression *exp = mkexpr(&lexer->loc); exp->type = EXPR_ASSERT; struct token tok; @@ -950,7 +986,7 @@ parse_measurement_expression(struct lexer *lexer) { trace(TR_PARSE, "measurement"); - struct ast_expression *exp = xcalloc(1, sizeof(struct ast_expression)); + struct ast_expression *exp = mkexpr(&lexer->loc); exp->type = EXPR_MEASURE; struct token tok; @@ -985,7 +1021,7 @@ parse_call_expression(struct lexer *lexer, struct ast_expression *lvalue) struct token tok; want(lexer, T_LPAREN, &tok); - struct ast_expression *expr = xcalloc(1, sizeof(struct ast_expression)); + struct ast_expression *expr = mkexpr(&lexer->loc); expr->type = EXPR_CALL; expr->call.lvalue = lvalue; @@ -1026,7 +1062,7 @@ parse_index_slice_expression(struct lexer *lexer, struct ast_expression *lvalue) { trenter(TR_PARSE, "slice-index"); - struct ast_expression *exp = xcalloc(1, sizeof(struct ast_expression)); + struct ast_expression *exp = mkexpr(&lexer->loc); struct ast_expression *start = NULL, *end = NULL; struct token tok; want(lexer, T_LBRACKET, &tok); @@ -1115,7 +1151,7 @@ parse_postfix_expression(struct lexer *lexer, struct ast_expression *lvalue) trenter(TR_PARSE, "field-access"); want(lexer, T_NAME, &tok); struct ast_expression *exp = - xcalloc(sizeof(struct ast_expression), 1); + mkexpr(&lexer->loc); exp->type = EXPR_ACCESS; exp->access.type = ACCESS_FIELD; exp->access._struct = lvalue; @@ -1183,7 +1219,7 @@ parse_unary_expression(struct lexer *lexer) case T_LNOT: // ! case T_TIMES: // * case T_BAND: // & - exp = xcalloc(1, sizeof(struct ast_expression)); + exp = mkexpr(&lexer->loc); exp->type = EXPR_UNARITHM; exp->unarithm.op = unop_for_token(tok.token); if (tok.token == T_BAND) { @@ -1222,7 +1258,7 @@ parse_cast_expression(struct lexer *lexer, struct ast_expression *value) return value; } - struct ast_expression *exp = xcalloc(1, sizeof(struct ast_expression)); + struct ast_expression *exp = mkexpr(&lexer->loc); exp->type = EXPR_CAST; exp->cast.kind = kind; exp->cast.value = value; @@ -1344,7 +1380,7 @@ parse_bin_expression(struct lexer *lexer, struct ast_expression *lvalue, int i) lex(lexer, &tok); } - struct ast_expression *e = xcalloc(1, sizeof(struct ast_expression)); + struct ast_expression *e = mkexpr(&lexer->loc); e->type = EXPR_BINARITHM; e->binarithm.op = op; e->binarithm.lvalue = lvalue; @@ -1366,7 +1402,7 @@ static struct ast_expression * parse_if_expression(struct lexer *lexer) { trenter(TR_PARSE, "if"); - struct ast_expression *exp = xcalloc(1, sizeof(struct ast_expression)); + struct ast_expression *exp = mkexpr(&lexer->loc); exp->type = EXPR_IF; struct token tok = {0}; @@ -1399,7 +1435,7 @@ static struct ast_expression * parse_for_expression(struct lexer *lexer) { trenter(TR_PARSE, "for"); - struct ast_expression *exp = xcalloc(1, sizeof(struct ast_expression)); + struct ast_expression *exp = mkexpr(&lexer->loc); exp->type = EXPR_FOR; struct token tok = {0}; @@ -1459,7 +1495,7 @@ static struct ast_expression * parse_binding_list(struct lexer *lexer) { trenter(TR_PARSE, "binding-list"); - struct ast_expression *exp = xcalloc(1, sizeof(struct ast_expression)); + struct ast_expression *exp = mkexpr(&lexer->loc); exp->type = EXPR_BINDING; unsigned int flags = 0; @@ -1484,7 +1520,7 @@ parse_binding_list(struct lexer *lexer) while (more) { want(lexer, T_NAME, &tok); binding->name = tok.name; - binding->initializer = xcalloc(1, sizeof(struct ast_expression)); + binding->initializer = mkexpr(&lexer->loc); binding->flags = flags; switch (lex(lexer, &tok)) { @@ -1523,7 +1559,7 @@ parse_assignment(struct lexer *lexer, struct ast_expression *object, bool indire { trenter(TR_PARSE, "assign"); struct ast_expression *value = parse_complex_expression(lexer); - struct ast_expression *expr = xcalloc(1, sizeof(struct ast_expression)); + struct ast_expression *expr = mkexpr(&lexer->loc); expr->type = EXPR_ASSIGN; expr->assign.object = object; expr->assign.value = value; @@ -1595,7 +1631,7 @@ parse_control_statement(struct lexer *lexer) { trenter(TR_PARSE, "control-expression"); - struct ast_expression *exp = xcalloc(1, sizeof(struct ast_expression)); + struct ast_expression *exp = mkexpr(&lexer->loc); struct token tok; switch (lex(lexer, &tok)) { @@ -1631,7 +1667,7 @@ parse_expression_list(struct lexer *lexer) trenter(TR_PARSE, "expression-list"); want(lexer, T_LBRACE, NULL); - struct ast_expression *exp = xcalloc(1, sizeof(struct ast_expression)); + struct ast_expression *exp = mkexpr(&lexer->loc); struct ast_expression_list *cur = &exp->list; struct ast_expression_list **next = &cur->next; exp->type = EXPR_LIST; @@ -1870,6 +1906,9 @@ static void parse_decl(struct lexer *lexer, struct ast_decl *decl) { struct token tok = {0}; + decl->loc.lineno = lexer->loc.lineno; + decl->loc.colno = lexer->loc.colno; + decl->loc.path = strdup(lexer->loc.path); switch (lex(lexer, &tok)) { case T_CONST: case T_LET: