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:
M | include/ast.h | | | 6 | ++++++ |
M | include/lex.h | | | 1 | + |
M | src/check.c | | | 111 | ++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------- |
M | src/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(¶ms->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: