mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
MSVC compatibility
This commit is contained in:
@@ -8,7 +8,6 @@
|
||||
|
||||
#define MAX_OUTPUT_FILES 1000000
|
||||
#define MAX_MODULES 100000
|
||||
|
||||
GlobalContext global_context;
|
||||
BuildTarget active_target;
|
||||
|
||||
|
||||
@@ -2385,10 +2385,11 @@ bool obj_format_linking_supported(ObjectFormatType format_type);
|
||||
bool linker(const char *output_file, const char **files, unsigned file_count);
|
||||
void platform_linker(const char *output_file, const char **files, unsigned file_count);
|
||||
|
||||
#define TRY_AST_OR(_ast_stmt, _res) ({ Ast* _ast = (_ast_stmt); if (!ast_ok(_ast)) return _res; _ast; })
|
||||
#define TRY_EXPR_OR(_expr_stmt, _res) ({ Expr* _expr = (_expr_stmt); if (!expr_ok(_expr)) return _res; _expr; })
|
||||
#define TRY_TYPE_OR(_type_stmt, _res) ({ TypeInfo* _type = (_type_stmt); if (!type_info_ok(_type)) return _res; _type; })
|
||||
#define TRY_TYPE_REAL_OR(_type_stmt, _res) ({ Type* _type = (_type_stmt); if (!type_ok(_type)) return _res; _type; })
|
||||
#define TRY_DECL_OR(_decl_stmt, _res) ({ Decl* _decl = (_decl_stmt); if (!decl_ok(_decl)) return _res; _decl; })
|
||||
|
||||
#define CAT(a,b) CAT2(a,b) // force expand
|
||||
#define CAT2(a,b) a##b // actually concatenate
|
||||
#define TEMP(X) CAT(X, __LINE__)
|
||||
#define ASSIGN_AST_ELSE(_assign, _ast_stmt, _res) Ast* TEMP(_ast) = (_ast_stmt); if (!ast_ok(TEMP(_ast))) return _res; _assign = TEMP(_ast)
|
||||
#define ASSIGN_EXPR_ELSE(_assign, _expr_stmt, _res) Expr* TEMP(_expr) = (_expr_stmt); if (!expr_ok(TEMP(_expr))) return _res; _assign = TEMP(_expr)
|
||||
#define ASSIGN_TYPE_ELSE(_assign, _type_stmt, _res) TypeInfo* TEMP(_type) = (_type_stmt); if (!type_info_ok(TEMP(_type))) return _res; _assign = TEMP(_type)
|
||||
#define ASSIGN_DECL_ELSE(_assign, _decl_stmt, _res) Decl* TEMP(_decl) = (_decl_stmt); if (!decl_ok(TEMP(_decl))) return _res; _assign = TEMP(_decl)
|
||||
|
||||
|
||||
@@ -81,8 +81,15 @@ static inline Expr *parse_catch_unwrap(Context *context)
|
||||
{
|
||||
advance_and_verify(context, TOKEN_CATCH);
|
||||
Expr *expr = expr_new(EXPR_CATCH_UNWRAP, source_span_from_token_id(context->prev_tok));
|
||||
expr->catch_unwrap_expr.type = parse_next_is_decl(context) ? TRY_TYPE_OR(parse_type(context), poisoned_expr) : NULL;
|
||||
expr->catch_unwrap_expr.variable = TRY_EXPR_OR(parse_for_try_expr(context), poisoned_expr);
|
||||
if (parse_next_is_decl(context))
|
||||
{
|
||||
ASSIGN_TYPE_ELSE(expr->catch_unwrap_expr.type, parse_type(context), poisoned_expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
expr->catch_unwrap_expr.type = NULL;
|
||||
}
|
||||
ASSIGN_EXPR_ELSE(expr->catch_unwrap_expr.variable, parse_for_try_expr(context), poisoned_expr);
|
||||
if (!try_consume(context, TOKEN_EQ))
|
||||
{
|
||||
if (expr->catch_unwrap_expr.type)
|
||||
@@ -99,14 +106,14 @@ static inline Expr *parse_catch_unwrap(Context *context)
|
||||
{
|
||||
do
|
||||
{
|
||||
Expr *init_expr = TRY_EXPR_OR(parse_expr(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(Expr *init_expr, parse_expr(context), poisoned_expr);
|
||||
vec_add(expr->catch_unwrap_expr.exprs, init_expr);
|
||||
} while (try_consume(context, TOKEN_COMMA));
|
||||
CONSUME_OR(TOKEN_RPAREN, poisoned_expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
Expr *init_expr = TRY_EXPR_OR(parse_expr(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(Expr *init_expr, parse_expr(context), poisoned_expr);
|
||||
vec_add(expr->catch_unwrap_expr.exprs, init_expr);
|
||||
}
|
||||
RANGE_EXTEND_PREV(expr);
|
||||
@@ -122,9 +129,9 @@ static inline Expr *parse_try_unwrap(Context *context)
|
||||
advance_and_verify(context, TOKEN_TRY);
|
||||
if (parse_next_is_decl(context))
|
||||
{
|
||||
expr->try_unwrap_expr.type = TRY_TYPE_OR(parse_type(context), poisoned_expr);
|
||||
ASSIGN_TYPE_ELSE(expr->try_unwrap_expr.type, parse_type(context), poisoned_expr);
|
||||
}
|
||||
expr->try_unwrap_expr.variable = TRY_EXPR_OR(parse_for_try_expr(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(expr->try_unwrap_expr.variable, parse_for_try_expr(context), poisoned_expr);
|
||||
if (expr->try_unwrap_expr.type && expr->try_unwrap_expr.variable->expr_kind != EXPR_IDENTIFIER)
|
||||
{
|
||||
SEMA_ERROR(expr->try_unwrap_expr.variable, "Expected a variable name after the type.");
|
||||
@@ -132,7 +139,7 @@ static inline Expr *parse_try_unwrap(Context *context)
|
||||
}
|
||||
if (try_consume(context, TOKEN_EQ))
|
||||
{
|
||||
expr->try_unwrap_expr.init = TRY_EXPR_OR(parse_for_try_expr(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(expr->try_unwrap_expr.init, parse_for_try_expr(context), poisoned_expr);
|
||||
}
|
||||
RANGE_EXTEND_PREV(expr);
|
||||
return expr;
|
||||
@@ -145,17 +152,17 @@ static inline Expr *parse_try_unwrap(Context *context)
|
||||
static inline Expr *parse_try_unwrap_chain(Context *context)
|
||||
{
|
||||
Expr **unwraps = NULL;
|
||||
Expr *first_unwrap = TRY_EXPR_OR(parse_try_unwrap(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(Expr *first_unwrap , parse_try_unwrap(context), poisoned_expr);
|
||||
vec_add(unwraps, first_unwrap);
|
||||
while (try_consume(context, TOKEN_AND))
|
||||
{
|
||||
if (next_is_try_unwrap(context))
|
||||
{
|
||||
Expr *expr = TRY_EXPR_OR(parse_try_unwrap(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(Expr *expr, parse_try_unwrap(context), poisoned_expr);
|
||||
vec_add(unwraps, expr);
|
||||
continue;
|
||||
}
|
||||
Expr *next_unwrap = TRY_EXPR_OR(parse_for_try_expr(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(Expr *next_unwrap, parse_for_try_expr(context), poisoned_expr);
|
||||
vec_add(unwraps, next_unwrap);
|
||||
}
|
||||
Expr *try_unwrap_chain = EXPR_NEW_EXPR(EXPR_TRY_UNWRAP_CHAIN, first_unwrap);
|
||||
@@ -185,7 +192,7 @@ Expr *parse_cond(Context *context)
|
||||
{
|
||||
if (next_is_try_unwrap(context))
|
||||
{
|
||||
Expr *try_unwrap = TRY_EXPR_OR(parse_try_unwrap_chain(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(Expr *try_unwrap, parse_try_unwrap_chain(context), poisoned_expr);
|
||||
vec_add(decl_expr->cond_expr, try_unwrap);
|
||||
if (tok_is(context, TOKEN_COMMA))
|
||||
{
|
||||
@@ -196,7 +203,7 @@ Expr *parse_cond(Context *context)
|
||||
}
|
||||
if (next_is_catch_unwrap(context))
|
||||
{
|
||||
Expr *catch_unwrap = TRY_EXPR_OR(parse_catch_unwrap(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(Expr *catch_unwrap, parse_catch_unwrap(context), poisoned_expr);
|
||||
vec_add(decl_expr->cond_expr, catch_unwrap);
|
||||
if (tok_is(context, TOKEN_COMMA))
|
||||
{
|
||||
@@ -207,14 +214,14 @@ Expr *parse_cond(Context *context)
|
||||
}
|
||||
if (parse_next_is_decl(context))
|
||||
{
|
||||
Decl *decl = TRY_DECL_OR(parse_decl(context), poisoned_expr);
|
||||
ASSIGN_DECL_ELSE(Decl *decl, parse_decl(context), poisoned_expr);
|
||||
Expr *expr = expr_new(EXPR_DECL, decl->span);
|
||||
expr->decl_expr = decl;
|
||||
vec_add(decl_expr->cond_expr, expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
Expr *expr = TRY_EXPR_OR(parse_expr(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(Expr *expr, parse_expr(context), poisoned_expr);
|
||||
vec_add(decl_expr->cond_expr, expr);
|
||||
}
|
||||
if (!try_consume(context, TOKEN_COMMA)) break;
|
||||
@@ -251,11 +258,12 @@ static bool parse_param_path(Context *context, DesignatorElement ***path)
|
||||
DesignatorElement *element = CALLOCS(DesignatorElement);
|
||||
element->kind = DESIGNATOR_ARRAY;
|
||||
advance_and_verify(context, TOKEN_LBRACKET);
|
||||
element->index_expr = TRY_EXPR_OR(parse_expr(context), false);
|
||||
ASSIGN_EXPR_ELSE(element->index_expr, parse_expr(context), false);
|
||||
|
||||
// Possible range
|
||||
if (try_consume(context, TOKEN_DOTDOT))
|
||||
{
|
||||
element->index_end_expr = TRY_EXPR_OR(parse_expr(context), false);
|
||||
ASSIGN_EXPR_ELSE(element->index_end_expr, parse_expr(context), false);
|
||||
element->kind = DESIGNATOR_RANGE;
|
||||
}
|
||||
CONSUME_OR(TOKEN_RBRACKET, false);
|
||||
@@ -303,7 +311,7 @@ bool parse_arg_list(Context *context, Expr ***result, TokenType param_end, bool
|
||||
CONSUME_OR(TOKEN_EQ, false);
|
||||
|
||||
// Now parse the rest
|
||||
expr->designator_expr.value = TRY_EXPR_OR(parse_expr_or_initializer_list(context), false);
|
||||
ASSIGN_EXPR_ELSE(expr->designator_expr.value, parse_expr_or_initializer_list(context), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -311,7 +319,7 @@ bool parse_arg_list(Context *context, Expr ***result, TokenType param_end, bool
|
||||
{
|
||||
*unsplat = try_consume(context, TOKEN_ELLIPSIS);
|
||||
}
|
||||
expr = TRY_EXPR_OR(parse_expr_or_initializer_list(context), false);
|
||||
ASSIGN_EXPR_ELSE(expr, parse_expr_or_initializer_list(context), false);
|
||||
}
|
||||
vec_add(*result, expr);
|
||||
if (!try_consume(context, TOKEN_COMMA))
|
||||
@@ -335,7 +343,7 @@ static Expr *parse_macro_expansion(Context *context, Expr *left)
|
||||
assert(!left && "Unexpected left hand side");
|
||||
Expr *macro_expression = EXPR_NEW_TOKEN(EXPR_MACRO_EXPANSION, context->tok);
|
||||
advance_and_verify(context, TOKEN_AT);
|
||||
Expr *inner = TRY_EXPR_OR(parse_precedence(context, PREC_MACRO), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(Expr *inner, parse_precedence(context, PREC_MACRO), poisoned_expr);
|
||||
macro_expression->macro_expansion_expr.inner = inner;
|
||||
assert(inner);
|
||||
RANGE_EXTEND_PREV(macro_expression);
|
||||
@@ -356,7 +364,7 @@ Expr *parse_expression_list(Context *context)
|
||||
while (1)
|
||||
{
|
||||
Expr *expr = NULL;
|
||||
expr = TRY_EXPR_OR(parse_expr_or_initializer_list(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(expr, parse_expr_or_initializer_list(context), poisoned_expr);
|
||||
vec_add(expr_list->expression_list, expr);
|
||||
if (!try_consume(context, TOKEN_COMMA)) break;
|
||||
}
|
||||
@@ -377,7 +385,7 @@ static Expr *parse_typeof_expr(Context *context, Expr *left)
|
||||
{
|
||||
assert(!left && "Unexpected left hand side");
|
||||
Expr *expr = EXPR_NEW_TOKEN(EXPR_TYPEINFO, context->tok);
|
||||
TypeInfo *type = TRY_TYPE_OR(parse_type(context), poisoned_expr);
|
||||
ASSIGN_TYPE_ELSE(TypeInfo *type, parse_type(context), poisoned_expr);
|
||||
expr->span = type->span;
|
||||
expr->type_expr = type;
|
||||
return expr;
|
||||
@@ -432,12 +440,12 @@ static Expr *parse_ternary_expr(Context *context, Expr *left_side)
|
||||
else
|
||||
{
|
||||
advance_and_verify(context, TOKEN_QUESTION);
|
||||
Expr *true_expr = TRY_EXPR_OR(parse_precedence(context, PREC_TERNARY + 1), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(Expr *true_expr, parse_precedence(context, PREC_TERNARY + 1), poisoned_expr);
|
||||
expr_ternary->ternary_expr.then_expr = true_expr;
|
||||
CONSUME_OR(TOKEN_COLON, poisoned_expr);
|
||||
}
|
||||
|
||||
Expr *false_expr = TRY_EXPR_OR(parse_precedence(context, PREC_TERNARY + 1), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(Expr *false_expr, parse_precedence(context, PREC_TERNARY + 1), poisoned_expr);
|
||||
expr_ternary->ternary_expr.else_expr = false_expr;
|
||||
RANGE_EXTEND_PREV(expr_ternary);
|
||||
return expr_ternary;
|
||||
@@ -453,7 +461,7 @@ static Expr *parse_grouping_expr(Context *context, Expr *left)
|
||||
assert(!left && "Unexpected left hand side");
|
||||
Expr *expr = EXPR_NEW_TOKEN(EXPR_GROUP, context->tok);
|
||||
advance_and_verify(context, TOKEN_LPAREN);
|
||||
expr->group_expr = TRY_EXPR_OR(parse_expr(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(expr->group_expr, parse_expr(context), poisoned_expr);
|
||||
CONSUME_OR(TOKEN_RPAREN, poisoned_expr);
|
||||
if (expr->group_expr->expr_kind == EXPR_TYPEINFO && try_consume(context, TOKEN_LPAREN))
|
||||
{
|
||||
@@ -463,7 +471,7 @@ static Expr *parse_grouping_expr(Context *context, Expr *left)
|
||||
SEMA_TOKEN_ERROR(context->tok, "Unexpected start of a block '{' here. If you intended a compound literal, remove the () around the type.");
|
||||
return poisoned_expr;
|
||||
}
|
||||
Expr *cast_expr = TRY_EXPR_OR(parse_expr(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(Expr *cast_expr, parse_expr(context), poisoned_expr);
|
||||
CONSUME_OR(TOKEN_RPAREN, poisoned_expr);
|
||||
expr->expr_kind = EXPR_CAST;
|
||||
expr->cast_expr.type_info = info;
|
||||
@@ -551,18 +559,18 @@ static Expr *parse_binary(Context *context, Expr *left_side)
|
||||
Expr *right_side;
|
||||
if (TOKEN_IS(TOKEN_LBRACE) && operator_type == TOKEN_EQ)
|
||||
{
|
||||
right_side = TRY_EXPR_OR(parse_initializer_list(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(right_side, parse_initializer_list(context), poisoned_expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assignment operators have precedence right -> left.
|
||||
if (rules[operator_type].precedence == PREC_ASSIGNMENT)
|
||||
{
|
||||
right_side = TRY_EXPR_OR(parse_precedence(context, PREC_ASSIGNMENT), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(right_side, parse_precedence(context, PREC_ASSIGNMENT), poisoned_expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
right_side = TRY_EXPR_OR(parse_precedence(context, rules[operator_type].precedence + 1), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(right_side, parse_precedence(context, rules[operator_type].precedence + 1), poisoned_expr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -611,7 +619,7 @@ static Expr *parse_call_expr(Context *context, Expr *left)
|
||||
}
|
||||
if (TOKEN_IS(TOKEN_LBRACE))
|
||||
{
|
||||
call->call_expr.body = TRY_AST_OR(parse_compound_stmt(context), poisoned_expr);
|
||||
ASSIGN_AST_ELSE(call->call_expr.body, parse_compound_stmt(context), poisoned_expr);
|
||||
}
|
||||
if (!parse_attributes(context, &call->call_expr.attributes)) return false;
|
||||
return call;
|
||||
@@ -636,7 +644,7 @@ static Expr *parse_subscript_expr(Context *context, Expr *left)
|
||||
{
|
||||
// Might be ^ prefix
|
||||
from_back = try_consume(context, TOKEN_BIT_XOR);
|
||||
index = TRY_EXPR_OR(parse_expr(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(index, parse_expr(context), poisoned_expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -652,7 +660,7 @@ static Expr *parse_subscript_expr(Context *context, Expr *left)
|
||||
if (!TOKEN_IS(TOKEN_RBRACKET))
|
||||
{
|
||||
end_from_back = try_consume(context, TOKEN_BIT_XOR);
|
||||
end = TRY_EXPR_OR(parse_expr(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(end, parse_expr(context), poisoned_expr);
|
||||
}
|
||||
}
|
||||
CONSUME_OR(TOKEN_RBRACKET, poisoned_expr);
|
||||
@@ -683,7 +691,7 @@ static Expr *parse_access_expr(Context *context, Expr *left)
|
||||
advance_and_verify(context, TOKEN_DOT);
|
||||
Expr *access_expr = EXPR_NEW_EXPR(EXPR_ACCESS, left);
|
||||
access_expr->access_expr.parent = left;
|
||||
access_expr->access_expr.child = TRY_EXPR_OR(parse_precedence(context, PREC_CALL + 1), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(access_expr->access_expr.child, parse_precedence(context, PREC_CALL + 1), poisoned_expr);
|
||||
RANGE_EXTEND_PREV(access_expr);
|
||||
return access_expr;
|
||||
}
|
||||
@@ -720,7 +728,7 @@ static Expr *parse_ct_call(Context *context, Expr *left)
|
||||
expr->ct_call_expr.token_type = context->tok.type;
|
||||
advance(context);
|
||||
CONSUME_OR(TOKEN_LPAREN, poisoned_expr);
|
||||
Expr *internal = TRY_EXPR_OR(parse_precedence(context, PREC_FIRST + 1), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(Expr *internal, parse_precedence(context, PREC_FIRST + 1), poisoned_expr);
|
||||
ExprFlatElement *flat_path = NULL;
|
||||
if (context->tok.type == TOKEN_DOT || context->tok.type == TOKEN_LBRACKET)
|
||||
{
|
||||
@@ -729,7 +737,7 @@ static Expr *parse_ct_call(Context *context, Expr *left)
|
||||
ExprFlatElement flat_element;
|
||||
if (try_consume(context, TOKEN_LBRACKET))
|
||||
{
|
||||
Expr *int_expr = TRY_EXPR_OR(parse_expr(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(Expr *int_expr, parse_expr(context), poisoned_expr);
|
||||
if (int_expr->expr_kind != EXPR_CONST || int_expr->const_expr.const_kind != CONST_INTEGER)
|
||||
{
|
||||
SEMA_TOKEN_ERROR(context->tok, "Expected an integer index.");
|
||||
@@ -829,7 +837,7 @@ static Expr *parse_try_expr(Context *context, Expr *left)
|
||||
return poisoned_expr;
|
||||
}
|
||||
}
|
||||
try_expr->try_expr.expr = TRY_EXPR_OR(parse_expr(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(try_expr->try_expr.expr, parse_expr(context), poisoned_expr);
|
||||
try_expr->try_expr.is_try = is_try;
|
||||
CONSUME_OR(TOKEN_RPAREN, poisoned_expr);
|
||||
RANGE_EXTEND_PREV(try_expr);
|
||||
@@ -857,7 +865,7 @@ static Expr *parse_else_expr(Context *context, Expr *left)
|
||||
case TOKEN_CONTINUE:
|
||||
case TOKEN_NEXTCASE:
|
||||
{
|
||||
Ast *ast = TRY_AST_OR(parse_jump_stmt_no_eos(context), poisoned_expr);
|
||||
ASSIGN_AST_ELSE(Ast *ast, parse_jump_stmt_no_eos(context), poisoned_expr);
|
||||
else_expr->else_expr.is_jump = true;
|
||||
else_expr->else_expr.else_stmt = ast;
|
||||
if (!TOKEN_IS(TOKEN_EOS))
|
||||
@@ -868,8 +876,10 @@ static Expr *parse_else_expr(Context *context, Expr *left)
|
||||
break;
|
||||
}
|
||||
default:
|
||||
else_expr->else_expr.else_expr = TRY_EXPR_OR(parse_precedence(context, PREC_ASSIGNMENT), poisoned_expr);
|
||||
{
|
||||
ASSIGN_EXPR_ELSE(else_expr->else_expr.else_expr, parse_precedence(context, PREC_ASSIGNMENT), poisoned_expr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return else_expr;
|
||||
}
|
||||
@@ -878,7 +888,7 @@ static Expr *parse_placeholder(Context *context, Expr *left)
|
||||
{
|
||||
assert(!left && "Had left hand side");
|
||||
advance_and_verify(context, TOKEN_PLACEHOLDER);
|
||||
Expr *expr = TRY_EXPR_OR(parse_expr(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(Expr *expr, parse_expr(context), poisoned_expr);
|
||||
CONSUME_OR(TOKEN_RBRACE, poisoned_expr);
|
||||
|
||||
if (expr->expr_kind != EXPR_IDENTIFIER && TOKTYPE(expr->identifier_expr.identifier) != TOKEN_CONST_IDENT)
|
||||
@@ -1256,7 +1266,7 @@ Expr *parse_type_compound_literal_expr_after_type(Context *context, TypeInfo *ty
|
||||
advance_and_verify(context, TOKEN_LPAREN);
|
||||
Expr *expr = expr_new(EXPR_COMPOUND_LITERAL, type_info->span);
|
||||
expr->expr_compound_literal.type_info = type_info;
|
||||
expr->expr_compound_literal.initializer = TRY_EXPR_OR(parse_initializer_list(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(expr->expr_compound_literal.initializer, parse_initializer_list(context), poisoned_expr);
|
||||
CONSUME_OR(TOKEN_RPAREN, poisoned_expr);
|
||||
RANGE_EXTEND_PREV(expr);
|
||||
return expr;
|
||||
@@ -1280,11 +1290,11 @@ Expr *parse_type_expression_with_path(Context *context, Path *path)
|
||||
type->unresolved.name_loc = context->tok.id;
|
||||
advance_and_verify(context, TOKEN_TYPE_IDENT);
|
||||
RANGE_EXTEND_PREV(type);
|
||||
type = TRY_TYPE_OR(parse_type_with_base(context, type), poisoned_expr);
|
||||
ASSIGN_TYPE_ELSE(type, parse_type_with_base(context, type), poisoned_expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
type = TRY_TYPE_OR(parse_type(context), poisoned_expr);
|
||||
ASSIGN_TYPE_ELSE(type, parse_type(context), poisoned_expr);
|
||||
}
|
||||
if (!type->virtual_type && TOKEN_IS(TOKEN_LPAREN) && context->next_tok.type == TOKEN_LBRACE)
|
||||
{
|
||||
|
||||
@@ -139,7 +139,7 @@ static inline Decl *parse_ct_if_top_level(Context *context)
|
||||
{
|
||||
Decl *ct = DECL_NEW(DECL_CT_IF, VISIBLE_LOCAL);
|
||||
advance_and_verify(context, TOKEN_CT_IF);
|
||||
ct->ct_if_decl.expr = TRY_EXPR_OR(parse_const_paren_expr(context), poisoned_decl);
|
||||
ASSIGN_EXPR_ELSE(ct->ct_if_decl.expr, parse_const_paren_expr(context), poisoned_decl);
|
||||
|
||||
if (!parse_top_level_block(context, &ct->ct_if_decl.then, TOKEN_CT_ENDIF, TOKEN_CT_ELIF, TOKEN_CT_ELSE)) return poisoned_decl;
|
||||
|
||||
@@ -148,7 +148,8 @@ static inline Decl *parse_ct_if_top_level(Context *context)
|
||||
{
|
||||
advance_and_verify(context, TOKEN_CT_ELIF);
|
||||
Decl *ct_elif = DECL_NEW(DECL_CT_ELIF, VISIBLE_LOCAL);
|
||||
ct_elif->ct_elif_decl.expr = TRY_EXPR_OR(parse_const_paren_expr(context), poisoned_decl);
|
||||
ASSIGN_EXPR_ELSE(ct_elif->ct_elif_decl.expr, parse_const_paren_expr(context), poisoned_decl);
|
||||
|
||||
if (!parse_top_level_block(context, &ct_elif->ct_elif_decl.then, TOKEN_CT_ENDIF, TOKEN_CT_ELIF, TOKEN_CT_ELSE)) return poisoned_decl;
|
||||
ct_if_decl->elif = ct_elif;
|
||||
ct_if_decl = &ct_elif->ct_elif_decl;
|
||||
@@ -183,7 +184,7 @@ static inline Decl *parse_ct_case(Context *context)
|
||||
case TOKEN_CT_CASE:
|
||||
decl = DECL_NEW(DECL_CT_CASE, VISIBLE_LOCAL);
|
||||
advance(context);
|
||||
decl->ct_case_decl.type = TRY_TYPE_OR(parse_type(context), poisoned_decl);
|
||||
ASSIGN_TYPE_ELSE(decl->ct_case_decl.type, parse_type(context), poisoned_decl);
|
||||
break;
|
||||
default:
|
||||
SEMA_TOKEN_ERROR(context->tok, "Expected a $case or $default statement here.");
|
||||
@@ -194,7 +195,7 @@ static inline Decl *parse_ct_case(Context *context)
|
||||
{
|
||||
TokenType type = context->tok.type;
|
||||
if (type == TOKEN_CT_DEFAULT || type == TOKEN_CT_CASE || type == TOKEN_LBRACE) break;
|
||||
Decl *stmt = TRY_DECL_OR(parse_top_level_statement(context), poisoned_decl);
|
||||
ASSIGN_DECL_ELSE(Decl *stmt, parse_top_level_statement(context), poisoned_decl);
|
||||
vec_add(decl->ct_case_decl.body, stmt);
|
||||
}
|
||||
return decl;
|
||||
@@ -209,12 +210,12 @@ static inline Decl *parse_ct_switch_top_level(Context *context)
|
||||
{
|
||||
Decl *ct = DECL_NEW(DECL_CT_SWITCH, VISIBLE_LOCAL);
|
||||
advance_and_verify(context, TOKEN_CT_SWITCH);
|
||||
ct->ct_switch_decl.expr = TRY_EXPR_OR(parse_const_paren_expr(context), poisoned_decl);
|
||||
ASSIGN_EXPR_ELSE(ct->ct_switch_decl.expr, parse_const_paren_expr(context), poisoned_decl);
|
||||
|
||||
CONSUME_OR(TOKEN_LBRACE, poisoned_decl);
|
||||
while (!try_consume(context, TOKEN_RBRACE))
|
||||
{
|
||||
Decl *result = TRY_DECL_OR(parse_ct_case(context), poisoned_decl);
|
||||
ASSIGN_DECL_ELSE(Decl *result, parse_ct_case(context), poisoned_decl);
|
||||
vec_add(ct->ct_switch_decl.cases, result);
|
||||
}
|
||||
return ct;
|
||||
@@ -545,7 +546,7 @@ static inline TypeInfo *parse_base_type(Context *context)
|
||||
{
|
||||
TypeInfo *type_info = type_info_new(TYPE_INFO_EXPRESSION, source_span_from_token_id(context->prev_tok));
|
||||
CONSUME_OR(TOKEN_LPAREN, poisoned_type_info);
|
||||
type_info->unresolved_type_expr = TRY_EXPR_OR(parse_expr(context), poisoned_type_info);
|
||||
ASSIGN_EXPR_ELSE(type_info->unresolved_type_expr, parse_expr(context), poisoned_type_info);
|
||||
CONSUME_OR(TOKEN_RPAREN, poisoned_type_info);
|
||||
RANGE_EXTEND_PREV(type_info);
|
||||
return type_info;
|
||||
@@ -656,7 +657,7 @@ static inline TypeInfo *parse_array_type_index(Context *context, TypeInfo *type)
|
||||
}
|
||||
TypeInfo *array = type_info_new(TYPE_INFO_ARRAY, type->span);
|
||||
array->array.base = type;
|
||||
array->array.len = TRY_EXPR_OR(parse_expr(context), poisoned_type_info);
|
||||
ASSIGN_EXPR_ELSE(array->array.len, parse_expr(context), poisoned_type_info);
|
||||
CONSUME_OR(TOKEN_RBRACKET, poisoned_type_info);
|
||||
RANGE_EXTEND_PREV(array);
|
||||
return array;
|
||||
@@ -708,7 +709,7 @@ TypeInfo *parse_type_with_base(Context *context, TypeInfo *type_info)
|
||||
*/
|
||||
TypeInfo *parse_type(Context *context)
|
||||
{
|
||||
TypeInfo *base = TRY_TYPE_OR(parse_base_type(context), poisoned_type_info);
|
||||
ASSIGN_TYPE_ELSE(TypeInfo *base, parse_base_type(context), poisoned_type_info);
|
||||
return parse_type_with_base(context, base);
|
||||
}
|
||||
|
||||
@@ -744,7 +745,7 @@ Decl *parse_decl_after_type(Context *context, TypeInfo *type)
|
||||
return poisoned_decl;
|
||||
}
|
||||
advance_and_verify(context, TOKEN_EQ);
|
||||
decl->var.init_expr = TRY_EXPR_OR(parse_initializer(context), poisoned_decl);
|
||||
ASSIGN_EXPR_ELSE(decl->var.init_expr, parse_initializer(context), poisoned_decl);
|
||||
}
|
||||
return decl;
|
||||
}
|
||||
@@ -764,11 +765,11 @@ Decl *parse_decl(Context *context)
|
||||
|
||||
bool is_static = try_consume(context, TOKEN_STATIC);
|
||||
|
||||
TypeInfo *type = TRY_TYPE_OR(parse_type(context), poisoned_decl);
|
||||
ASSIGN_TYPE_ELSE(TypeInfo *type, parse_type(context), poisoned_decl);
|
||||
|
||||
bool failable = try_consume(context, TOKEN_BANG);
|
||||
|
||||
Decl *decl = TRY_DECL_OR(parse_decl_after_type(context, type), poisoned_decl);
|
||||
ASSIGN_DECL_ELSE(Decl *decl, parse_decl_after_type(context, type), poisoned_decl);
|
||||
if (failable && decl->var.unwrap)
|
||||
{
|
||||
SEMA_ERROR(decl, "You cannot use unwrap with a failable variable.");
|
||||
@@ -795,7 +796,7 @@ static Decl *parse_const_declaration(Context *context, Visibility visibility)
|
||||
|
||||
if (parse_next_is_decl(context))
|
||||
{
|
||||
decl->var.type_info = TRY_TYPE_OR(parse_type(context), poisoned_decl);
|
||||
ASSIGN_TYPE_ELSE(decl->var.type_info, parse_type(context), poisoned_decl);
|
||||
}
|
||||
decl->name = TOKSTR(context->tok);
|
||||
decl->name_token = context->tok.id;
|
||||
@@ -803,7 +804,7 @@ static Decl *parse_const_declaration(Context *context, Visibility visibility)
|
||||
|
||||
CONSUME_OR(TOKEN_EQ, poisoned_decl);
|
||||
|
||||
decl->var.init_expr = TRY_EXPR_OR(parse_initializer(context), poisoned_decl);
|
||||
ASSIGN_EXPR_ELSE(decl->var.init_expr, parse_initializer(context), poisoned_decl);
|
||||
|
||||
return decl;
|
||||
}
|
||||
@@ -855,7 +856,7 @@ static inline Decl *parse_incremental_array(Context *context)
|
||||
return poisoned_decl;
|
||||
}
|
||||
Decl *decl = decl_new(DECL_ARRAY_VALUE, name.id, VISIBLE_LOCAL);
|
||||
decl->incr_array_decl = TRY_EXPR_OR(parse_initializer(context), poisoned_decl);
|
||||
ASSIGN_EXPR_ELSE(decl->incr_array_decl, parse_initializer(context), poisoned_decl);
|
||||
TRY_CONSUME_EOS_OR(poisoned_decl);
|
||||
return decl;
|
||||
}
|
||||
@@ -949,7 +950,7 @@ bool parse_attributes(Context *context, Attr ***attributes_ref)
|
||||
|
||||
if (TOKEN_IS(TOKEN_LPAREN))
|
||||
{
|
||||
attr->expr = TRY_EXPR_OR(parse_const_paren_expr(context), false);
|
||||
ASSIGN_EXPR_ELSE(attr->expr, parse_const_paren_expr(context), false);
|
||||
}
|
||||
const char *name = TOKSTR(attr->name);
|
||||
VECEACH(*attributes_ref, i)
|
||||
@@ -979,7 +980,7 @@ bool parse_attributes(Context *context, Attr ***attributes_ref)
|
||||
*/
|
||||
static inline Decl *parse_global_declaration(Context *context, Visibility visibility)
|
||||
{
|
||||
TypeInfo *type = TRY_TYPE_OR(parse_type(context), poisoned_decl);
|
||||
ASSIGN_TYPE_ELSE(TypeInfo *type, parse_type(context), poisoned_decl);
|
||||
|
||||
bool failable = try_consume(context, TOKEN_BANG);
|
||||
|
||||
@@ -1008,7 +1009,7 @@ static inline Decl *parse_global_declaration(Context *context, Visibility visibi
|
||||
if (!parse_attributes(context, &decl->attributes)) return poisoned_decl;
|
||||
if (try_consume(context, TOKEN_EQ))
|
||||
{
|
||||
decl->var.init_expr = TRY_EXPR_OR(parse_initializer(context), poisoned_decl);
|
||||
ASSIGN_EXPR_ELSE(decl->var.init_expr, parse_initializer(context), poisoned_decl);
|
||||
}
|
||||
TRY_CONSUME_EOS_OR(poisoned_decl);
|
||||
return decl;
|
||||
@@ -1023,7 +1024,7 @@ static inline Decl *parse_global_declaration(Context *context, Visibility visibi
|
||||
static inline bool parse_param_decl(Context *context, Visibility parent_visibility, Decl*** parameters, bool require_name)
|
||||
{
|
||||
TokenId first = context->tok.id;
|
||||
TypeInfo *type = TRY_TYPE_OR(parse_type(context), false);
|
||||
ASSIGN_TYPE_ELSE(TypeInfo *type, parse_type(context), false);
|
||||
bool vararg = try_consume(context, TOKEN_ELLIPSIS);
|
||||
Decl *param = decl_new_var(context->tok.id, type, VARDECL_PARAM, parent_visibility);
|
||||
param->span = (SourceSpan) { first, context->tok.id };
|
||||
@@ -1051,7 +1052,7 @@ static inline bool parse_param_decl(Context *context, Visibility parent_visibili
|
||||
}
|
||||
if (name && try_consume(context, TOKEN_EQ))
|
||||
{
|
||||
param->var.init_expr = TRY_EXPR_OR(parse_initializer(context), false);
|
||||
ASSIGN_EXPR_ELSE(param->var.init_expr, parse_initializer(context), false);
|
||||
}
|
||||
|
||||
vec_add(*parameters, param);
|
||||
@@ -1082,7 +1083,7 @@ bool parse_parameters(Context *context, Visibility visibility, Decl ***params_re
|
||||
// so consequently we need fix this and ignore CT_TYPE_IDENT
|
||||
if (!ellipsis && context_next_is_type_and_not_ident(context) && context->tok.type != TOKEN_CT_TYPE_IDENT )
|
||||
{
|
||||
type = TRY_TYPE_OR(parse_type(context), false);
|
||||
ASSIGN_TYPE_ELSE(type, parse_type(context), false);
|
||||
ellipsis = try_consume(context, TOKEN_ELLIPSIS);
|
||||
}
|
||||
|
||||
@@ -1156,7 +1157,7 @@ bool parse_parameters(Context *context, Visibility visibility, Decl ***params_re
|
||||
advance(context);
|
||||
if (try_consume(context, TOKEN_EQ))
|
||||
{
|
||||
param->var.init_expr = TRY_EXPR_OR(parse_initializer(context), false);
|
||||
ASSIGN_EXPR_ELSE(param->var.init_expr, parse_initializer(context), false);
|
||||
}
|
||||
}
|
||||
var_arg_found |= ellipsis;
|
||||
@@ -1280,7 +1281,8 @@ bool parse_struct_body(Context *context, Decl *parent)
|
||||
was_inline = true;
|
||||
advance(context);
|
||||
}
|
||||
TypeInfo *type = TRY_TYPE_OR(parse_type(context), false);
|
||||
ASSIGN_TYPE_ELSE(TypeInfo *type, parse_type(context), false);
|
||||
|
||||
while (1)
|
||||
{
|
||||
EXPECT_OR(TOKEN_IDENT, false);
|
||||
@@ -1352,7 +1354,7 @@ static inline bool parse_bitstruct_body(Context *context, Decl *decl)
|
||||
|
||||
while (!try_consume(context, TOKEN_RBRACE))
|
||||
{
|
||||
TypeInfo *type = TRY_TYPE_OR(parse_type(context), false);
|
||||
ASSIGN_TYPE_ELSE(TypeInfo *type, parse_type(context), false);
|
||||
|
||||
if (!try_consume(context, TOKEN_IDENT))
|
||||
{
|
||||
@@ -1366,9 +1368,9 @@ static inline bool parse_bitstruct_body(Context *context, Decl *decl)
|
||||
}
|
||||
Decl *member_decl = decl_new_var(context->prev_tok, type, VARDECL_MEMBER, VISIBLE_LOCAL);
|
||||
CONSUME_OR(TOKEN_COLON, false);
|
||||
member_decl->var.start = TRY_EXPR_OR(parse_constant_expr(context), false);
|
||||
ASSIGN_EXPR_ELSE(member_decl->var.start, parse_constant_expr(context), false);
|
||||
CONSUME_OR(TOKEN_DOTDOT, false);
|
||||
member_decl->var.end = TRY_EXPR_OR(parse_constant_expr(context), false);
|
||||
ASSIGN_EXPR_ELSE(member_decl->var.end, parse_constant_expr(context), false);
|
||||
CONSUME_OR(TOKEN_EOS, false);
|
||||
vec_add(decl->bitstruct.members, member_decl);
|
||||
}
|
||||
@@ -1389,7 +1391,7 @@ static inline Decl *parse_bitstruct_declaration(Context *context, Visibility vis
|
||||
|
||||
CONSUME_OR(TOKEN_COLON, poisoned_decl);
|
||||
|
||||
decl->bitstruct.base_type = TRY_TYPE_OR(parse_type(context), poisoned_decl);
|
||||
ASSIGN_TYPE_ELSE(decl->bitstruct.base_type, parse_type(context), poisoned_decl);
|
||||
|
||||
if (!parse_attributes(context, &decl->attributes))
|
||||
{
|
||||
@@ -1407,7 +1409,7 @@ static inline Decl *parse_bitstruct_declaration(Context *context, Visibility vis
|
||||
|
||||
static inline Decl *parse_top_level_const_declaration(Context *context, Visibility visibility)
|
||||
{
|
||||
Decl *decl = TRY_DECL_OR(parse_const_declaration(context, visibility), poisoned_decl);
|
||||
ASSIGN_DECL_ELSE(Decl *decl, parse_const_declaration(context, visibility), poisoned_decl);
|
||||
TRY_CONSUME_EOS_OR(poisoned_decl);
|
||||
return decl;
|
||||
}
|
||||
@@ -1456,8 +1458,8 @@ static inline TypeInfo **parse_generic_parameters(Context *context)
|
||||
TypeInfo **types = NULL;
|
||||
while (!try_consume(context, TOKEN_GREATER))
|
||||
{
|
||||
TypeInfo *expr = TRY_TYPE_OR(parse_type(context), NULL);
|
||||
vec_add(types, expr);
|
||||
ASSIGN_TYPE_ELSE(TypeInfo *type_info, parse_type(context), NULL);
|
||||
vec_add(types, type_info);
|
||||
if (context->tok.type != TOKEN_RPAREN && context->tok.type != TOKEN_GREATER)
|
||||
{
|
||||
TRY_CONSUME_OR(TOKEN_COMMA, "Expected ',' after argument.", NULL);
|
||||
@@ -1507,7 +1509,7 @@ static inline Decl *parse_define_type(Context *context, Visibility visibility)
|
||||
decl->span.loc = start;
|
||||
decl->typedef_decl.is_func = true;
|
||||
decl->typedef_decl.is_distinct = distinct;
|
||||
TypeInfo *type_info = TRY_TYPE_OR(parse_type(context), poisoned_decl);
|
||||
ASSIGN_TYPE_ELSE(TypeInfo *type_info, parse_type(context), poisoned_decl);
|
||||
decl->typedef_decl.function_signature.rtype = type_info;
|
||||
if (try_consume(context, TOKEN_BANG))
|
||||
{
|
||||
@@ -1523,7 +1525,7 @@ static inline Decl *parse_define_type(Context *context, Visibility visibility)
|
||||
}
|
||||
|
||||
// 2. Now parse the type which we know is here.
|
||||
TypeInfo *type_info = TRY_TYPE_OR(parse_type(context), poisoned_decl);
|
||||
ASSIGN_TYPE_ELSE(TypeInfo *type_info, parse_type(context), poisoned_decl);
|
||||
|
||||
// 3. Do we have '<' if so it's a parameterized type e.g. foo::bar::Type<int, double>.
|
||||
if (try_consume(context, TOKEN_LESS))
|
||||
@@ -1671,7 +1673,7 @@ static inline bool parse_func_macro_header(Context *context, bool rtype_is_optio
|
||||
}
|
||||
|
||||
// 2. Now we must have a type - either that is the return type or the method type.
|
||||
rtype = TRY_TYPE_OR(parse_type(context), false);
|
||||
ASSIGN_TYPE_ELSE(rtype, parse_type(context), false);
|
||||
|
||||
// 3. We possibly have a failable return at this point.
|
||||
failable = try_consume(context, TOKEN_BANG);
|
||||
@@ -1679,7 +1681,7 @@ static inline bool parse_func_macro_header(Context *context, bool rtype_is_optio
|
||||
// 4. We might have a type here, if so then we read it.
|
||||
if (!TOKEN_IS(TOKEN_DOT) && context_next_is_type_and_not_ident(context))
|
||||
{
|
||||
method_type = TRY_TYPE_OR(parse_type(context), false);
|
||||
ASSIGN_TYPE_ELSE(method_type, parse_type(context), false);
|
||||
}
|
||||
|
||||
// 5. If we have a dot here, then we need to interpret this as method function.
|
||||
@@ -1737,7 +1739,7 @@ static inline Decl *parse_macro_declaration(Context *context, Visibility visibil
|
||||
TokenId block_parameter = {};
|
||||
if (!parse_macro_arguments(context, visibility, &decl->macro_decl.parameters, &decl->macro_decl.body_parameters, &block_parameter)) return poisoned_decl;
|
||||
decl->macro_decl.block_parameter = block_parameter;
|
||||
decl->macro_decl.body = TRY_AST_OR(parse_stmt(context), poisoned_decl);
|
||||
ASSIGN_AST_ELSE(decl->macro_decl.body, parse_stmt(context), poisoned_decl);
|
||||
return decl;
|
||||
}
|
||||
|
||||
@@ -1789,7 +1791,7 @@ static inline Decl *parse_error_declaration(Context *context, Visibility visibil
|
||||
}
|
||||
if (try_consume(context, TOKEN_EQ))
|
||||
{
|
||||
enum_const->enum_constant.expr = TRY_EXPR_OR(parse_expr(context), poisoned_decl);
|
||||
ASSIGN_EXPR_ELSE(enum_const->enum_constant.expr, parse_expr(context), poisoned_decl);
|
||||
}
|
||||
vec_add(decl->enums.values, enum_const);
|
||||
// Allow trailing ','
|
||||
@@ -1809,7 +1811,9 @@ static inline Decl *parse_error_declaration(Context *context, Visibility visibil
|
||||
*/
|
||||
static inline bool parse_enum_spec(Context *context, TypeInfo **type_ref, Decl*** parameters_ref, Visibility parent_visibility)
|
||||
{
|
||||
*type_ref = TRY_TYPE_OR(parse_type(context), false);
|
||||
|
||||
ASSIGN_TYPE_ELSE(*type_ref, parse_type(context), false);
|
||||
|
||||
if (!try_consume(context, TOKEN_LPAREN)) return true;
|
||||
while (!try_consume(context, TOKEN_RPAREN))
|
||||
{
|
||||
@@ -1894,7 +1898,7 @@ static inline Decl *parse_enum_declaration(Context *context, Visibility visibili
|
||||
}
|
||||
if (try_consume(context, TOKEN_EQ))
|
||||
{
|
||||
enum_const->enum_constant.expr = TRY_EXPR_OR(parse_expr(context), poisoned_decl);
|
||||
ASSIGN_EXPR_ELSE(enum_const->enum_constant.expr, parse_expr(context), poisoned_decl);
|
||||
}
|
||||
vec_add(decl->enums.values, enum_const);
|
||||
// Allow trailing ','
|
||||
@@ -1964,7 +1968,7 @@ static inline Decl *parse_func_definition(Context *context, Visibility visibilit
|
||||
|
||||
TRY_EXPECT_OR(TOKEN_LBRACE, "Expected the beginning of a block with '{'", poisoned_decl);
|
||||
|
||||
func->func_decl.body = TRY_AST_OR(parse_compound_stmt(context), poisoned_decl);
|
||||
ASSIGN_AST_ELSE(func->func_decl.body, parse_compound_stmt(context), poisoned_decl);
|
||||
|
||||
DEBUG_LOG("Finished parsing function %s", func->name);
|
||||
return func;
|
||||
@@ -1999,7 +2003,7 @@ static inline Decl *parse_interface_declaration(Context *context, Visibility vis
|
||||
SEMA_TOKEN_ERROR(context->tok, "Expected a function here.");
|
||||
return poisoned_decl;
|
||||
}
|
||||
Decl *function = TRY_DECL_OR(parse_func_definition(context, visibility, true), poisoned_decl);
|
||||
ASSIGN_DECL_ELSE(Decl *function, parse_func_definition(context, visibility, true), poisoned_decl);
|
||||
vec_add(decl->methods, function);
|
||||
}
|
||||
|
||||
@@ -2122,10 +2126,11 @@ static inline bool parse_doc_errors(Context *context, Ast *docs)
|
||||
|
||||
static inline bool parse_doc_contract(Context *context, Ast *docs)
|
||||
{
|
||||
docs->doc_directive.contract.decl_exprs = TRY_EXPR_OR(parse_cond(context), false);
|
||||
ASSIGN_EXPR_ELSE(docs->doc_directive.contract.decl_exprs, parse_cond(context), false);
|
||||
|
||||
if (try_consume(context, TOKEN_COLON))
|
||||
{
|
||||
docs->doc_directive.contract.comment = TRY_EXPR_OR(parse_expr(context), false);
|
||||
ASSIGN_EXPR_ELSE(docs->doc_directive.contract.comment, parse_expr(context), false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -2238,18 +2243,22 @@ Decl *parse_top_level_statement(Context *context)
|
||||
SEMA_TOKEN_ERROR(context->tok, "There are more than one doc comment in a row, that is not allowed.");
|
||||
return poisoned_decl;
|
||||
case TOKEN_DEFINE:
|
||||
decl = TRY_DECL_OR(parse_define(context, visibility), poisoned_decl);
|
||||
{
|
||||
ASSIGN_DECL_ELSE(decl, parse_define(context, visibility), poisoned_decl);
|
||||
break;
|
||||
}
|
||||
case TOKEN_ATTRIBUTE:
|
||||
TODO
|
||||
break;
|
||||
case TOKEN_FUNC:
|
||||
decl = TRY_DECL_OR(parse_func_definition(context, visibility, false), poisoned_decl);
|
||||
{
|
||||
ASSIGN_DECL_ELSE(decl, parse_func_definition(context, visibility, false), poisoned_decl);
|
||||
break;
|
||||
}
|
||||
case TOKEN_CT_ASSERT:
|
||||
if (!check_no_visibility_before(context, visibility)) return poisoned_decl;
|
||||
{
|
||||
Ast *ast = TRY_AST_OR(parse_ct_assert_stmt(context), false);
|
||||
ASSIGN_AST_ELSE(Ast *ast, parse_ct_assert_stmt(context), false);
|
||||
decl = decl_new(DECL_CT_ASSERT, ast->span.loc, visibility);
|
||||
decl->ct_assert_decl = ast;
|
||||
if (docs)
|
||||
@@ -2260,54 +2269,72 @@ Decl *parse_top_level_statement(Context *context)
|
||||
return decl;
|
||||
}
|
||||
case TOKEN_CT_IF:
|
||||
{
|
||||
if (!check_no_visibility_before(context, visibility)) return poisoned_decl;
|
||||
decl = TRY_DECL_OR(parse_ct_if_top_level(context), poisoned_decl);
|
||||
ASSIGN_DECL_ELSE(decl, parse_ct_if_top_level(context), poisoned_decl);
|
||||
if (docs)
|
||||
{
|
||||
SEMA_ERROR(docs, "Unexpected doc comment before $if, did you mean to use a regular comment?");
|
||||
return poisoned_decl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TOKEN_CT_SWITCH:
|
||||
{
|
||||
if (!check_no_visibility_before(context, visibility)) return poisoned_decl;
|
||||
decl = TRY_DECL_OR(parse_ct_switch_top_level(context), poisoned_decl);
|
||||
ASSIGN_DECL_ELSE(decl, parse_ct_switch_top_level(context), poisoned_decl);
|
||||
if (docs)
|
||||
{
|
||||
SEMA_ERROR(docs, "Unexpected doc comment before $switch, did you mean to use a regular comment?");
|
||||
return poisoned_decl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TOKEN_BITSTRUCT:
|
||||
decl = TRY_DECL_OR(parse_bitstruct_declaration(context, visibility), poisoned_decl);
|
||||
{
|
||||
ASSIGN_DECL_ELSE(decl, parse_bitstruct_declaration(context, visibility), poisoned_decl);
|
||||
break;
|
||||
}
|
||||
case TOKEN_CONST:
|
||||
decl = TRY_DECL_OR(parse_top_level_const_declaration(context, visibility), poisoned_decl);
|
||||
{
|
||||
ASSIGN_DECL_ELSE(decl, parse_top_level_const_declaration(context, visibility), poisoned_decl);
|
||||
break;
|
||||
}
|
||||
case TOKEN_INTERFACE:
|
||||
decl = TRY_DECL_OR(parse_interface_declaration(context, visibility), poisoned_decl);
|
||||
{
|
||||
ASSIGN_DECL_ELSE(decl, parse_interface_declaration(context, visibility), poisoned_decl);
|
||||
break;
|
||||
}
|
||||
case TOKEN_STRUCT:
|
||||
case TOKEN_UNION:
|
||||
decl = TRY_DECL_OR(parse_struct_declaration(context, visibility), poisoned_decl);
|
||||
{
|
||||
ASSIGN_DECL_ELSE(decl, parse_struct_declaration(context, visibility), poisoned_decl);
|
||||
break;
|
||||
}
|
||||
case TOKEN_GENERIC:
|
||||
case TOKEN_MACRO:
|
||||
decl = TRY_DECL_OR(parse_macro_declaration(context, visibility), poisoned_decl);
|
||||
{
|
||||
ASSIGN_DECL_ELSE(decl, parse_macro_declaration(context, visibility), poisoned_decl);
|
||||
break;
|
||||
}
|
||||
case TOKEN_ENUM:
|
||||
decl = TRY_DECL_OR(parse_enum_declaration(context, visibility), poisoned_decl);
|
||||
{
|
||||
ASSIGN_DECL_ELSE(decl, parse_enum_declaration(context, visibility), poisoned_decl);
|
||||
break;
|
||||
}
|
||||
case TOKEN_ERRTYPE:
|
||||
decl = TRY_DECL_OR(parse_error_declaration(context, visibility), poisoned_decl);
|
||||
{
|
||||
ASSIGN_DECL_ELSE(decl, parse_error_declaration(context, visibility), poisoned_decl);
|
||||
break;
|
||||
}
|
||||
case TOKEN_IDENT:
|
||||
if (context->next_tok.type == TOKEN_SCOPE)
|
||||
{
|
||||
decl = TRY_DECL_OR(parse_global_declaration(context, visibility), poisoned_decl);
|
||||
ASSIGN_DECL_ELSE(decl, parse_global_declaration(context, visibility), poisoned_decl);
|
||||
break;
|
||||
}
|
||||
if (!check_no_visibility_before(context, visibility)) return poisoned_decl;
|
||||
decl = TRY_DECL_OR(parse_incremental_array(context), poisoned_decl);
|
||||
ASSIGN_DECL_ELSE(decl, parse_incremental_array(context), poisoned_decl);
|
||||
if (docs)
|
||||
{
|
||||
SEMA_ERROR(docs,
|
||||
@@ -2333,8 +2360,10 @@ Decl *parse_top_level_statement(Context *context)
|
||||
SEMA_TOKEN_ERROR(context->tok, "Imports are only allowed directly after the module declaration.");
|
||||
return poisoned_decl;
|
||||
case TYPELIKE_TOKENS:
|
||||
decl = TRY_DECL_OR(parse_global_declaration(context, visibility), poisoned_decl);
|
||||
{
|
||||
ASSIGN_DECL_ELSE(decl, parse_global_declaration(context, visibility), poisoned_decl);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
SEMA_TOKEN_ERROR(context->tok, "Expected a top level declaration here.");
|
||||
return poisoned_decl;
|
||||
|
||||
@@ -18,7 +18,7 @@ Ast *parse_unreachable_stmt(Context *context);
|
||||
static inline Ast *parse_declaration_stmt(Context *context)
|
||||
{
|
||||
Ast *decl_stmt = AST_NEW_TOKEN(AST_DECLARE_STMT, context->tok);
|
||||
decl_stmt->declare_stmt = TRY_DECL_OR(parse_decl(context), poisoned_ast);
|
||||
ASSIGN_DECL_ELSE(decl_stmt->declare_stmt, parse_decl(context), poisoned_ast);
|
||||
CONSUME_OR(TOKEN_EOS, poisoned_ast);
|
||||
return decl_stmt;
|
||||
}
|
||||
@@ -147,7 +147,7 @@ static inline Ast* parse_asm_stmt(Context *context)
|
||||
advance_and_verify(context, TOKEN_ASM);
|
||||
ast->asm_stmt.is_volatile = try_consume(context, TOKEN_VOLATILE);
|
||||
CONSUME_OR(TOKEN_LPAREN, poisoned_ast);
|
||||
ast->asm_stmt.body = TRY_EXPR_OR(parse_expr(context), poisoned_ast);
|
||||
ASSIGN_EXPR_ELSE(ast->asm_stmt.body, parse_expr(context), poisoned_ast);
|
||||
ast->asm_stmt.is_volatile = true;
|
||||
CONSUME_OR(TOKEN_RPAREN, poisoned_ast);
|
||||
RANGE_EXTEND_PREV(ast);
|
||||
@@ -166,13 +166,13 @@ static inline Ast* parse_do_stmt(Context *context)
|
||||
|
||||
advance_and_verify(context, TOKEN_DO);
|
||||
|
||||
do_ast->do_stmt.flow.label = TRY_DECL_OR(parse_optional_label(context, do_ast), poisoned_ast);
|
||||
do_ast->do_stmt.body = TRY_AST(parse_stmt(context));
|
||||
ASSIGN_DECL_ELSE(do_ast->do_stmt.flow.label, parse_optional_label(context, do_ast), poisoned_ast);
|
||||
ASSIGN_AST_ELSE(do_ast->do_stmt.body, parse_stmt(context), poisoned_ast);
|
||||
|
||||
if (try_consume(context, TOKEN_WHILE))
|
||||
{
|
||||
CONSUME_OR(TOKEN_LPAREN, poisoned_ast);
|
||||
do_ast->do_stmt.expr = TRY_EXPR_OR(parse_expr(context), poisoned_ast);
|
||||
ASSIGN_EXPR_ELSE(do_ast->do_stmt.expr, parse_expr(context), poisoned_ast);
|
||||
CONSUME_OR(TOKEN_RPAREN, poisoned_ast);
|
||||
CONSUME_OR(TOKEN_EOS, poisoned_ast);
|
||||
}
|
||||
@@ -191,7 +191,7 @@ static inline Ast *parse_case_stmts(Context *context, TokenType case_type, Token
|
||||
Ast *compound = AST_NEW_TOKEN(AST_COMPOUND_STMT, context->tok);
|
||||
while (!token_type_ends_case(context->tok.type, case_type, default_type))
|
||||
{
|
||||
Ast *stmt = TRY_AST(parse_stmt(context));
|
||||
ASSIGN_AST_ELSE(Ast *stmt, parse_stmt(context), poisoned_ast);
|
||||
vec_add(compound->compound_stmt.stmts, stmt);
|
||||
}
|
||||
return compound;
|
||||
@@ -207,7 +207,7 @@ static inline Ast* parse_defer_stmt(Context *context)
|
||||
{
|
||||
advance_and_verify(context, TOKEN_DEFER);
|
||||
Ast *defer_stmt = AST_NEW_TOKEN(AST_DEFER_STMT, context->tok);
|
||||
defer_stmt->defer_stmt.body = TRY_AST(parse_stmt(context));
|
||||
ASSIGN_AST_ELSE(defer_stmt->defer_stmt.body, parse_stmt(context), poisoned_ast);
|
||||
return defer_stmt;
|
||||
}
|
||||
|
||||
@@ -220,12 +220,12 @@ static inline Ast* parse_while_stmt(Context *context)
|
||||
Ast *while_ast = AST_NEW_TOKEN(AST_WHILE_STMT, context->tok);
|
||||
advance_and_verify(context, TOKEN_WHILE);
|
||||
|
||||
while_ast->while_stmt.flow.label = TRY_DECL_OR(parse_optional_label(context, while_ast), poisoned_ast);
|
||||
ASSIGN_DECL_ELSE(while_ast->while_stmt.flow.label, parse_optional_label(context, while_ast), poisoned_ast);
|
||||
|
||||
CONSUME_OR(TOKEN_LPAREN, poisoned_ast);
|
||||
while_ast->while_stmt.cond = TRY_EXPR_OR(parse_cond(context), poisoned_ast);
|
||||
ASSIGN_EXPR_ELSE(while_ast->while_stmt.cond, parse_cond(context), poisoned_ast);
|
||||
CONSUME_OR(TOKEN_RPAREN, poisoned_ast);
|
||||
while_ast->while_stmt.body = TRY_AST(parse_stmt(context));
|
||||
ASSIGN_AST_ELSE(while_ast->while_stmt.body, parse_stmt(context), poisoned_ast);
|
||||
return while_ast;
|
||||
}
|
||||
|
||||
@@ -252,9 +252,9 @@ static inline Ast* parse_if_stmt(Context *context)
|
||||
{
|
||||
Ast *if_ast = AST_NEW_TOKEN(AST_IF_STMT, context->tok);
|
||||
advance_and_verify(context, TOKEN_IF);
|
||||
if_ast->if_stmt.flow.label = TRY_DECL_OR(parse_optional_label(context, if_ast), poisoned_ast);
|
||||
ASSIGN_DECL_ELSE(if_ast->if_stmt.flow.label, parse_optional_label(context, if_ast), poisoned_ast);
|
||||
CONSUME_OR(TOKEN_LPAREN, poisoned_ast);
|
||||
if_ast->if_stmt.cond = TRY_EXPR_OR(parse_cond(context), poisoned_ast);
|
||||
ASSIGN_EXPR_ELSE(if_ast->if_stmt.cond, parse_cond(context), poisoned_ast);
|
||||
CONSUME_OR(TOKEN_RPAREN, poisoned_ast);
|
||||
// Special case, we might have if ( ) { case ... }
|
||||
if (tok_is(context, TOKEN_LBRACE) && (context->next_tok.type == TOKEN_CASE || context->next_tok.type == TOKEN_DEFAULT))
|
||||
@@ -267,13 +267,13 @@ static inline Ast* parse_if_stmt(Context *context)
|
||||
}
|
||||
else
|
||||
{
|
||||
if_ast->if_stmt.then_body = TRY_AST(parse_stmt(context));
|
||||
ASSIGN_AST_ELSE(if_ast->if_stmt.then_body, parse_stmt(context), poisoned_ast);
|
||||
}
|
||||
if (!try_consume(context, TOKEN_ELSE))
|
||||
{
|
||||
return if_ast;
|
||||
}
|
||||
if_ast->if_stmt.else_body = TRY_AST(parse_stmt(context));
|
||||
ASSIGN_AST_ELSE(if_ast->if_stmt.else_body, parse_stmt(context), poisoned_ast);
|
||||
return if_ast;
|
||||
}
|
||||
|
||||
@@ -283,10 +283,11 @@ static bool parse_type_or_expr(Context *context, TypeInfo **type_info, Expr **ex
|
||||
{
|
||||
if (parse_next_is_case_type(context))
|
||||
{
|
||||
*type_info = TRY_TYPE_OR(parse_type(context), false);
|
||||
ASSIGN_TYPE_ELSE(*type_info, parse_type(context), false);
|
||||
return true;
|
||||
}
|
||||
*expr = TRY_EXPR_OR(parse_constant_expr(context), false);;
|
||||
ASSIGN_EXPR_ELSE(*expr, parse_constant_expr(context), false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -302,7 +303,7 @@ static inline Ast *parse_case_stmt(Context *context, TokenType case_type, TokenT
|
||||
{
|
||||
Ast *ast = AST_NEW_TOKEN(AST_CASE_STMT, context->tok);
|
||||
advance(context);
|
||||
ast->case_stmt.expr = TRY_EXPR_OR(parse_expr(context), poisoned_ast);
|
||||
ASSIGN_EXPR_ELSE(ast->case_stmt.expr, parse_expr(context), poisoned_ast);
|
||||
// Change type -> type.typeid
|
||||
if (ast->case_stmt.expr->expr_kind == EXPR_TYPEINFO)
|
||||
{
|
||||
@@ -310,7 +311,7 @@ static inline Ast *parse_case_stmt(Context *context, TokenType case_type, TokenT
|
||||
}
|
||||
TRY_CONSUME(TOKEN_COLON, "Missing ':' after case");
|
||||
extend_ast_with_prev_token(context, ast);
|
||||
ast->case_stmt.body = TRY_AST(parse_case_stmts(context, case_type, default_type));
|
||||
ASSIGN_AST_ELSE(ast->case_stmt.body, parse_case_stmts(context, case_type, default_type), poisoned_ast);
|
||||
return ast;
|
||||
}
|
||||
|
||||
@@ -324,7 +325,7 @@ static inline Ast *parse_default_stmt(Context *context, TokenType case_type, Tok
|
||||
advance(context);
|
||||
TRY_CONSUME_OR(TOKEN_COLON, "Expected ':' after 'default'.", poisoned_ast);
|
||||
extend_ast_with_prev_token(context, ast);
|
||||
ast->case_stmt.body = TRY_AST(parse_case_stmts(context, case_type, default_type));
|
||||
ASSIGN_AST_ELSE(ast->case_stmt.body, parse_case_stmts(context, case_type, default_type), poisoned_ast);
|
||||
ast->case_stmt.expr = NULL;
|
||||
return ast;
|
||||
}
|
||||
@@ -347,11 +348,11 @@ bool parse_switch_body(Context *context, Ast ***cases, TokenType case_type, Toke
|
||||
TokenType next = context->tok.type;
|
||||
if (next == case_type)
|
||||
{
|
||||
result = TRY_AST_OR(parse_case_stmt(context, case_type, default_type), false);
|
||||
ASSIGN_AST_ELSE(result, parse_case_stmt(context, case_type, default_type), false);
|
||||
}
|
||||
else if (next == default_type)
|
||||
{
|
||||
result = TRY_AST_OR(parse_default_stmt(context, case_type, default_type), false);
|
||||
ASSIGN_AST_ELSE(result, parse_default_stmt(context, case_type, default_type), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -372,9 +373,9 @@ static inline Ast* parse_switch_stmt(Context *context)
|
||||
{
|
||||
Ast *switch_ast = AST_NEW_TOKEN(AST_SWITCH_STMT, context->tok);
|
||||
advance_and_verify(context, TOKEN_SWITCH);
|
||||
switch_ast->switch_stmt.flow.label = TRY_DECL_OR(parse_optional_label(context, switch_ast), poisoned_ast);
|
||||
ASSIGN_DECL_ELSE(switch_ast->switch_stmt.flow.label, parse_optional_label(context, switch_ast), poisoned_ast);
|
||||
CONSUME_OR(TOKEN_LPAREN, poisoned_ast);
|
||||
switch_ast->switch_stmt.cond = TRY_EXPR_OR(parse_cond(context), poisoned_ast);
|
||||
ASSIGN_EXPR_ELSE(switch_ast->switch_stmt.cond, parse_cond(context), poisoned_ast);
|
||||
CONSUME_OR(TOKEN_RPAREN, poisoned_ast);
|
||||
|
||||
if (!parse_switch_body(context, &switch_ast->switch_stmt.cases, TOKEN_CASE, TOKEN_DEFAULT, false)) return poisoned_ast;
|
||||
@@ -396,12 +397,12 @@ static inline Ast* parse_for_stmt(Context *context)
|
||||
{
|
||||
Ast *ast = AST_NEW_TOKEN(AST_FOR_STMT, context->tok);
|
||||
advance_and_verify(context, TOKEN_FOR);
|
||||
ast->for_stmt.flow.label = TRY_DECL_OR(parse_optional_label(context, ast), poisoned_ast);
|
||||
ASSIGN_DECL_ELSE(ast->for_stmt.flow.label, parse_optional_label(context, ast), poisoned_ast);
|
||||
CONSUME_OR(TOKEN_LPAREN, poisoned_ast);
|
||||
|
||||
if (!TOKEN_IS(TOKEN_EOS))
|
||||
{
|
||||
ast->for_stmt.init = TRY_EXPR_OR(parse_cond(context), poisoned_ast);
|
||||
ASSIGN_EXPR_ELSE(ast->for_stmt.init, parse_cond(context), poisoned_ast);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -412,7 +413,7 @@ static inline Ast* parse_for_stmt(Context *context)
|
||||
|
||||
if (!TOKEN_IS(TOKEN_EOS))
|
||||
{
|
||||
ast->for_stmt.cond = TRY_EXPR_OR(parse_expr(context), poisoned_ast);
|
||||
ASSIGN_EXPR_ELSE(ast->for_stmt.cond, parse_expr(context), poisoned_ast);
|
||||
}
|
||||
|
||||
CONSUME_OR(TOKEN_EOS, poisoned_ast);
|
||||
@@ -425,7 +426,7 @@ static inline Ast* parse_for_stmt(Context *context)
|
||||
CONSUME_OR(TOKEN_RPAREN, poisoned_ast);
|
||||
|
||||
extend_ast_with_prev_token(context, ast);
|
||||
ast->for_stmt.body = TRY_AST(parse_stmt(context));
|
||||
ASSIGN_AST_ELSE(ast->for_stmt.body, parse_stmt(context), poisoned_ast);
|
||||
return ast;
|
||||
}
|
||||
|
||||
@@ -438,7 +439,8 @@ static inline bool parse_foreach_var(Context *context, Ast *foreach)
|
||||
// If we don't get foreach (foo ... or foreach (*foo ... then a type is expected.
|
||||
if (!TOKEN_IS(TOKEN_IDENT) && !TOKEN_IS(TOKEN_AMP))
|
||||
{
|
||||
type = TRY_TYPE_OR(parse_type(context), false);
|
||||
ASSIGN_TYPE_ELSE(type, parse_type(context), false);
|
||||
|
||||
failable = try_consume(context, TOKEN_BANG);
|
||||
// Add the failable to the type for nicer error reporting.
|
||||
RANGE_EXTEND_PREV(type);
|
||||
@@ -471,7 +473,7 @@ static inline Ast* parse_foreach_stmt(Context *context)
|
||||
{
|
||||
Ast *ast = AST_NEW_TOKEN(AST_FOREACH_STMT, context->tok);
|
||||
advance_and_verify(context, TOKEN_FOREACH);
|
||||
ast->foreach_stmt.flow.label = TRY_DECL_OR(parse_optional_label(context, ast), poisoned_ast);
|
||||
ASSIGN_DECL_ELSE(ast->foreach_stmt.flow.label, parse_optional_label(context, ast), poisoned_ast);
|
||||
CONSUME_OR(TOKEN_LPAREN, poisoned_ast);
|
||||
|
||||
// Parse the first variable.
|
||||
@@ -491,12 +493,12 @@ static inline Ast* parse_foreach_stmt(Context *context)
|
||||
|
||||
CONSUME_OR(TOKEN_COLON, poisoned_ast);
|
||||
|
||||
ast->foreach_stmt.enumeration = TRY_EXPR_OR(parse_initializer(context), poisoned_ast);
|
||||
ASSIGN_EXPR_ELSE(ast->foreach_stmt.enumeration, parse_initializer(context), poisoned_ast);
|
||||
|
||||
CONSUME_OR(TOKEN_RPAREN, poisoned_ast);
|
||||
|
||||
extend_ast_with_prev_token(context, ast);
|
||||
ast->foreach_stmt.body = TRY_AST(parse_stmt(context));
|
||||
ASSIGN_AST_ELSE(ast->foreach_stmt.body, parse_stmt(context), poisoned_ast);
|
||||
return ast;
|
||||
}
|
||||
|
||||
@@ -567,7 +569,7 @@ static inline Ast* parse_break(Context *context)
|
||||
static inline Ast *parse_expr_stmt(Context *context)
|
||||
{
|
||||
Ast *stmt = AST_NEW_TOKEN(AST_EXPR_STMT, context->tok);
|
||||
stmt->expr_stmt = TRY_EXPR_OR(parse_expr(context), poisoned_ast);
|
||||
ASSIGN_EXPR_ELSE(stmt->expr_stmt, parse_expr(context), poisoned_ast);
|
||||
TRY_CONSUME_EOS();
|
||||
return stmt;
|
||||
}
|
||||
@@ -576,7 +578,7 @@ static inline Ast *parse_expr_stmt(Context *context)
|
||||
|
||||
static inline Ast *parse_decl_or_expr_stmt(Context *context)
|
||||
{
|
||||
Expr *expr = TRY_EXPR_OR(parse_expr(context), poisoned_ast);
|
||||
ASSIGN_EXPR_ELSE(Expr *expr, parse_expr(context), poisoned_ast);
|
||||
Ast *ast = ast_calloc();
|
||||
ast->span = expr->span;
|
||||
bool failable = false;
|
||||
@@ -590,7 +592,7 @@ static inline Ast *parse_decl_or_expr_stmt(Context *context)
|
||||
if (expr->expr_kind == EXPR_TYPEINFO)
|
||||
{
|
||||
ast->ast_kind = AST_DECLARE_STMT;
|
||||
ast->declare_stmt = TRY_DECL_OR(parse_decl_after_type(context, expr->type_expr), poisoned_ast);
|
||||
ASSIGN_DECL_ELSE(ast->declare_stmt, parse_decl_after_type(context, expr->type_expr), poisoned_ast);
|
||||
ast->declare_stmt->var.failable = failable;
|
||||
}
|
||||
else
|
||||
@@ -621,7 +623,7 @@ static inline Ast *parse_var_stmt(Context *context)
|
||||
advance(context);
|
||||
if (try_consume(context, TOKEN_EQ))
|
||||
{
|
||||
decl->var.init_expr = TRY_EXPR_OR(parse_expr(context), poisoned_ast);
|
||||
ASSIGN_EXPR_ELSE(decl->var.init_expr, parse_expr(context), poisoned_ast);
|
||||
}
|
||||
break;
|
||||
case TOKEN_CT_TYPE_IDENT:
|
||||
@@ -629,7 +631,7 @@ static inline Ast *parse_var_stmt(Context *context)
|
||||
advance(context);
|
||||
if (try_consume(context, TOKEN_EQ))
|
||||
{
|
||||
decl->var.type_info = TRY_TYPE_OR(parse_type(context), poisoned_ast);
|
||||
ASSIGN_TYPE_ELSE(decl->var.type_info, parse_type(context), poisoned_ast);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -651,7 +653,7 @@ static inline Ast* parse_ct_compound_stmt(Context *context)
|
||||
{
|
||||
TokenType token = context->tok.type;
|
||||
if (token == TOKEN_CT_ELSE || token == TOKEN_CT_ELIF || token == TOKEN_CT_ENDIF) break;
|
||||
Ast *stmt = TRY_AST(parse_stmt(context));
|
||||
ASSIGN_AST_ELSE(Ast *stmt, parse_stmt(context), poisoned_ast);
|
||||
vec_add(stmts->ct_compound_stmt, stmt);
|
||||
RANGE_EXTEND_PREV(stmts);
|
||||
}
|
||||
@@ -667,7 +669,7 @@ static inline Ast* parse_ct_else_stmt(Context *context)
|
||||
Ast *ast = AST_NEW_TOKEN(AST_CT_ELSE_STMT, context->tok);
|
||||
advance_and_verify(context, TOKEN_CT_ELSE);
|
||||
TRY_CONSUME(TOKEN_COLON, "$else needs a ':', did you forget it?");
|
||||
ast->ct_else_stmt = TRY_AST(parse_ct_compound_stmt(context));
|
||||
ASSIGN_AST_ELSE(ast->ct_else_stmt, parse_ct_compound_stmt(context), poisoned_ast);
|
||||
return ast;
|
||||
}
|
||||
|
||||
@@ -679,16 +681,17 @@ static inline Ast *parse_ct_elif_stmt(Context *context)
|
||||
{
|
||||
Ast *ast = AST_NEW_TOKEN(AST_CT_ELIF_STMT, context->tok);
|
||||
advance_and_verify(context, TOKEN_CT_ELIF);
|
||||
ast->ct_elif_stmt.expr = TRY_EXPR_OR(parse_const_paren_expr(context), poisoned_ast);
|
||||
ASSIGN_EXPR_ELSE(ast->ct_elif_stmt.expr, parse_const_paren_expr(context), poisoned_ast);
|
||||
TRY_CONSUME(TOKEN_COLON, "$elif needs a ':' after the expression, did you forget it?");
|
||||
ast->ct_elif_stmt.then = TRY_AST(parse_ct_compound_stmt(context));
|
||||
ASSIGN_AST_ELSE(ast->ct_elif_stmt.then, parse_ct_compound_stmt(context), poisoned_ast);
|
||||
|
||||
if (TOKEN_IS(TOKEN_CT_ELIF))
|
||||
{
|
||||
ast->ct_elif_stmt.elif = TRY_AST(parse_ct_elif_stmt(context));
|
||||
ASSIGN_AST_ELSE(ast->ct_elif_stmt.elif, parse_ct_elif_stmt(context), poisoned_ast);
|
||||
}
|
||||
else if (TOKEN_IS(TOKEN_CT_ELSE))
|
||||
{
|
||||
ast->ct_elif_stmt.elif = TRY_AST(parse_ct_else_stmt(context));
|
||||
ASSIGN_AST_ELSE(ast->ct_elif_stmt.elif, parse_ct_else_stmt(context), poisoned_ast);
|
||||
}
|
||||
return ast;
|
||||
}
|
||||
@@ -702,16 +705,17 @@ static inline Ast* parse_ct_if_stmt(Context *context)
|
||||
{
|
||||
Ast *ast = AST_NEW_TOKEN(AST_CT_IF_STMT, context->tok);
|
||||
advance_and_verify(context, TOKEN_CT_IF);
|
||||
ast->ct_if_stmt.expr = TRY_EXPR_OR(parse_const_paren_expr(context), poisoned_ast);
|
||||
ASSIGN_EXPR_ELSE(ast->ct_if_stmt.expr, parse_const_paren_expr(context), poisoned_ast);
|
||||
TRY_CONSUME(TOKEN_COLON, "$if needs a ':' after the expression, did you forget it?");
|
||||
ast->ct_if_stmt.then = TRY_AST(parse_ct_compound_stmt(context));
|
||||
ASSIGN_AST_ELSE(ast->ct_if_stmt.then, parse_ct_compound_stmt(context), poisoned_ast);
|
||||
|
||||
if (TOKEN_IS(TOKEN_CT_ELIF))
|
||||
{
|
||||
ast->ct_if_stmt.elif = TRY_AST(parse_ct_elif_stmt(context));
|
||||
ASSIGN_AST_ELSE(ast->ct_if_stmt.elif, parse_ct_elif_stmt(context), poisoned_ast);
|
||||
}
|
||||
else if (TOKEN_IS(TOKEN_CT_ELSE))
|
||||
{
|
||||
ast->ct_if_stmt.elif = TRY_AST(parse_ct_else_stmt(context));
|
||||
ASSIGN_AST_ELSE(ast->ct_if_stmt.elif, parse_ct_else_stmt(context), poisoned_ast);
|
||||
}
|
||||
advance_and_verify(context, TOKEN_CT_ENDIF);
|
||||
RANGE_EXTEND_PREV(ast);
|
||||
@@ -734,7 +738,7 @@ static inline Ast *parse_return(Context *context)
|
||||
ast->return_stmt.defer = 0;
|
||||
if (!TOKEN_IS(TOKEN_EOS))
|
||||
{
|
||||
ast->return_stmt.expr = TRY_EXPR_OR(parse_expr(context), poisoned_ast);
|
||||
ASSIGN_EXPR_ELSE(ast->return_stmt.expr, parse_expr(context), poisoned_ast);
|
||||
}
|
||||
return ast;
|
||||
}
|
||||
@@ -748,7 +752,7 @@ static inline Ast *parse_return(Context *context)
|
||||
static Ast *parse_volatile_stmt(Context *context)
|
||||
{
|
||||
Ast *ast = AST_NEW_TOKEN(AST_VOLATILE_STMT, context->tok);
|
||||
ast->volatile_stmt = TRY_AST_OR(parse_compound_stmt(context), poisoned_ast);
|
||||
ASSIGN_AST_ELSE(ast->volatile_stmt, parse_compound_stmt(context), poisoned_ast);
|
||||
return ast;
|
||||
}
|
||||
|
||||
@@ -777,9 +781,10 @@ static inline Ast* parse_ct_for_stmt(Context *context)
|
||||
ast->ct_for_stmt.value = context->tok.id;
|
||||
TRY_CONSUME_OR(TOKEN_CT_IDENT, "Expected a compile time variable", poisoned_ast);
|
||||
TRY_CONSUME_OR(TOKEN_COLON, "Expected ':'.", poisoned_ast);
|
||||
ast->ct_for_stmt.expr = TRY_EXPR_OR(parse_expr(context), poisoned_ast);
|
||||
ASSIGN_EXPR_ELSE(ast->ct_for_stmt.expr, parse_expr(context), poisoned_ast);
|
||||
CONSUME_OR(TOKEN_RPAREN, poisoned_ast);
|
||||
ast->ct_for_stmt.body = TRY_AST(parse_stmt(context));
|
||||
ASSIGN_AST_ELSE(ast->ct_for_stmt.body, parse_stmt(context), poisoned_ast);
|
||||
|
||||
return ast;
|
||||
}
|
||||
|
||||
@@ -802,7 +807,7 @@ static inline Ast* parse_ct_switch_stmt(Context *context)
|
||||
{
|
||||
Ast *ast = AST_NEW_TOKEN(AST_CT_SWITCH_STMT, context->tok);
|
||||
advance_and_verify(context, TOKEN_CT_SWITCH);
|
||||
ast->ct_switch_stmt.cond = TRY_EXPR_OR(parse_const_paren_expr(context), poisoned_ast);
|
||||
ASSIGN_EXPR_ELSE(ast->ct_switch_stmt.cond, parse_const_paren_expr(context), poisoned_ast);
|
||||
TRY_CONSUME(TOKEN_COLON, "Expected ':' after $switch expression, did you forget it?");
|
||||
Ast **cases = NULL;
|
||||
while (!try_consume(context, TOKEN_CT_ENDSWITCH))
|
||||
@@ -811,11 +816,11 @@ static inline Ast* parse_ct_switch_stmt(Context *context)
|
||||
TokenType next = context->tok.type;
|
||||
if (next == TOKEN_CT_CASE)
|
||||
{
|
||||
result = TRY_AST_OR(parse_case_stmt(context, TOKEN_CT_CASE, TOKEN_CT_DEFAULT), poisoned_ast);
|
||||
ASSIGN_AST_ELSE(result, parse_case_stmt(context, TOKEN_CT_CASE, TOKEN_CT_DEFAULT), poisoned_ast);
|
||||
}
|
||||
else if (next == TOKEN_CT_DEFAULT)
|
||||
{
|
||||
result = TRY_AST_OR(parse_default_stmt(context, TOKEN_CT_CASE, TOKEN_CT_DEFAULT), poisoned_ast);
|
||||
ASSIGN_AST_ELSE(result, parse_default_stmt(context, TOKEN_CT_CASE, TOKEN_CT_DEFAULT), poisoned_ast);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -834,10 +839,11 @@ static inline Ast *parse_assert_stmt(Context *context)
|
||||
Ast *ast = AST_NEW_TOKEN(AST_ASSERT_STMT, context->tok);
|
||||
advance_and_verify(context, TOKEN_ASSERT);
|
||||
TRY_CONSUME_OR(TOKEN_LPAREN, "'assert' needs a '(' here, did you forget it?", poisoned_ast);
|
||||
ast->assert_stmt.expr = TRY_EXPR_OR(parse_assert_expr(context), poisoned_ast);
|
||||
ASSIGN_EXPR_ELSE(ast->assert_stmt.expr, parse_assert_expr(context), poisoned_ast);
|
||||
|
||||
if (try_consume(context, TOKEN_COMMA))
|
||||
{
|
||||
ast->assert_stmt.message = TRY_EXPR_OR(parse_expr(context), poisoned_ast);
|
||||
ASSIGN_EXPR_ELSE(ast->assert_stmt.message, parse_expr(context), poisoned_ast);
|
||||
}
|
||||
TRY_CONSUME_OR(TOKEN_RPAREN, "The ending ')' was expected here.", poisoned_ast);
|
||||
TRY_CONSUME_EOS();
|
||||
@@ -856,10 +862,11 @@ Ast *parse_ct_assert_stmt(Context *context)
|
||||
Ast *ast = AST_NEW_TOKEN(AST_CT_ASSERT, context->tok);
|
||||
advance_and_verify(context, TOKEN_CT_ASSERT);
|
||||
TRY_CONSUME_OR(TOKEN_LPAREN, "'$assert' needs a '(' here, did you forget it?", poisoned_ast);
|
||||
ast->ct_assert_stmt.expr = TRY_EXPR_OR(parse_constant_expr(context), poisoned_ast);
|
||||
ASSIGN_EXPR_ELSE(ast->ct_assert_stmt.expr, parse_constant_expr(context), poisoned_ast);
|
||||
|
||||
if (try_consume(context, TOKEN_COMMA))
|
||||
{
|
||||
ast->ct_assert_stmt.message = TRY_EXPR_OR(parse_constant_expr(context), poisoned_ast);
|
||||
ASSIGN_EXPR_ELSE(ast->ct_assert_stmt.message, parse_constant_expr(context), poisoned_ast);
|
||||
}
|
||||
TRY_CONSUME_OR(TOKEN_RPAREN, "The ending ')' was expected here.", poisoned_ast);
|
||||
TRY_CONSUME_EOS();
|
||||
@@ -892,7 +899,7 @@ Ast *parse_stmt(Context *context)
|
||||
return parse_expr_stmt(context);
|
||||
case TOKEN_RETURN:
|
||||
{
|
||||
Ast *ast = TRY_AST(parse_return(context));
|
||||
ASSIGN_AST_ELSE(Ast *ast, parse_return(context), poisoned_ast);
|
||||
RETURN_AFTER_EOS(ast);
|
||||
}
|
||||
case TOKEN_IF:
|
||||
@@ -911,7 +918,7 @@ Ast *parse_stmt(Context *context)
|
||||
return parse_foreach_stmt(context);
|
||||
case TOKEN_CONTINUE:
|
||||
{
|
||||
Ast *ast = TRY_AST(parse_continue(context));
|
||||
ASSIGN_AST_ELSE(Ast *ast, parse_continue(context), poisoned_ast);
|
||||
RETURN_AFTER_EOS(ast);
|
||||
}
|
||||
case TOKEN_CASE:
|
||||
@@ -920,12 +927,12 @@ Ast *parse_stmt(Context *context)
|
||||
return poisoned_ast;
|
||||
case TOKEN_BREAK:
|
||||
{
|
||||
Ast *ast = TRY_AST(parse_break(context));
|
||||
ASSIGN_AST_ELSE(Ast *ast, parse_break(context), poisoned_ast);
|
||||
RETURN_AFTER_EOS(ast);
|
||||
}
|
||||
case TOKEN_NEXTCASE:
|
||||
{
|
||||
Ast *ast = TRY_AST(parse_next(context));
|
||||
ASSIGN_AST_ELSE(Ast *ast, parse_next(context), poisoned_ast);
|
||||
RETURN_AFTER_EOS(ast);
|
||||
}
|
||||
case TOKEN_ASM:
|
||||
@@ -1117,7 +1124,7 @@ Ast* parse_compound_stmt(Context *context)
|
||||
Ast *ast = AST_NEW_TOKEN(AST_COMPOUND_STMT, context->tok);
|
||||
while (!try_consume(context, TOKEN_RBRACE))
|
||||
{
|
||||
Ast *stmt = TRY_AST(parse_stmt(context));
|
||||
ASSIGN_AST_ELSE(Ast *stmt, parse_stmt(context), poisoned_ast);
|
||||
vec_add(ast->compound_stmt.stmts, stmt);
|
||||
}
|
||||
return ast;
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#define TRY_CONSUME_EOS() TRY_CONSUME_EOS_OR(poisoned_ast)
|
||||
#define RETURN_AFTER_EOS(_ast) extend_ast_with_prev_token(context, ast); TRY_CONSUME_EOS_OR(poisoned_ast); return _ast
|
||||
|
||||
#define TRY_AST(_ast_stmt) TRY_AST_OR(_ast_stmt, poisoned_ast)
|
||||
|
||||
#define CHECK_EXPR(_expr) do { if (!expr_ok(_expr)) return _expr; } while(0)
|
||||
|
||||
@@ -122,7 +121,7 @@ static inline bool expect_ident(Context *context, const char* name)
|
||||
static inline Expr *parse_const_paren_expr(Context *context)
|
||||
{
|
||||
CONSUME_OR(TOKEN_LPAREN, poisoned_expr);
|
||||
Expr *expr = TRY_EXPR_OR(parse_constant_expr(context), poisoned_expr);
|
||||
ASSIGN_EXPR_ELSE(Expr *expr, parse_constant_expr(context), poisoned_expr);
|
||||
CONSUME_OR(TOKEN_RPAREN, poisoned_expr);
|
||||
return expr;
|
||||
}
|
||||
|
||||
@@ -5461,7 +5461,7 @@ static inline bool sema_analyse_identifier_path_string(Context *context, SourceS
|
||||
}
|
||||
else
|
||||
{
|
||||
decl = TRY_DECL_OR(sema_resolve_string_symbol(context, symbol, expr->span, path, report_missing), report_missing);
|
||||
ASSIGN_DECL_ELSE(decl, sema_resolve_string_symbol(context, symbol, expr->span, path, report_missing), false);
|
||||
if (!decl) return true;
|
||||
if (!sema_analyse_decl(context, decl)) return false;
|
||||
if (decl->decl_kind == DECL_TYPEDEF)
|
||||
@@ -5775,8 +5775,10 @@ static inline bool sema_expr_resolve_maybe_identifier(Context *c, Expr *expr, De
|
||||
{
|
||||
case EXPR_CONST_IDENTIFIER:
|
||||
case EXPR_IDENTIFIER:
|
||||
*decl_ref = TRY_DECL_OR(sema_resolve_normal_symbol(c, expr->identifier_expr.identifier, expr->identifier_expr.path, false), false);
|
||||
{
|
||||
ASSIGN_DECL_ELSE(*decl_ref, sema_resolve_normal_symbol(c, expr->identifier_expr.identifier, expr->identifier_expr.path, false), false);
|
||||
return true;
|
||||
}
|
||||
case EXPR_TYPEINFO:
|
||||
if (expr->resolve_status == RESOLVE_DONE)
|
||||
{
|
||||
@@ -5788,10 +5790,8 @@ static inline bool sema_expr_resolve_maybe_identifier(Context *c, Expr *expr, De
|
||||
SEMA_ERROR(expr, "Expected a plain type name here.");
|
||||
return false;
|
||||
}
|
||||
*decl_ref = TRY_DECL_OR(sema_resolve_normal_symbol(c,
|
||||
expr->type_expr->unresolved.name_loc,
|
||||
expr->type_expr->unresolved.path,
|
||||
false), false);
|
||||
ASSIGN_DECL_ELSE(*decl_ref, sema_resolve_normal_symbol(c, expr->type_expr->unresolved.name_loc,
|
||||
expr->type_expr->unresolved.path, false), false);
|
||||
return true;
|
||||
case EXPR_CONST:
|
||||
switch (expr->const_expr.const_kind)
|
||||
|
||||
Reference in New Issue
Block a user