aboutsummaryrefslogtreecommitdiff
path: root/src/parser.cpp
diff options
context:
space:
mode:
authorgingerBill <gingerBill@users.noreply.github.com>2026-01-15 18:03:09 +0000
committerGitHub <noreply@github.com>2026-01-15 18:03:09 +0000
commitfaacac33ab6c03266e2c1407f027be811e97e093 (patch)
tree48b83381b47c4ae73dd5e87d1a3c71629cf176e9 /src/parser.cpp
parent7f509c01f1c912e2d4ccf5d8f1a029167fff107e (diff)
parent59ae82634ed69b019a8965d1120dd8c7c5a7a605 (diff)
Merge pull request #6135 from odin-lang/bill/must-tail
`#must_tail`
Diffstat (limited to 'src/parser.cpp')
-rw-r--r--src/parser.cpp28
1 files changed, 23 insertions, 5 deletions
diff --git a/src/parser.cpp b/src/parser.cpp
index 823021e04..fc55dae97 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -2176,7 +2176,7 @@ gb_internal bool ast_on_same_line(Token const &x, Ast *yp) {
return x.pos.line == y.pos.line;
}
-gb_internal Ast *parse_force_inlining_operand(AstFile *f, Token token) {
+gb_internal Ast *parse_inlining_or_tailing_operand(AstFile *f, Token token) {
Ast *expr = parse_unary_expr(f, false);
Ast *e = strip_or_return_expr(expr);
if (e == nullptr) {
@@ -2187,11 +2187,14 @@ gb_internal Ast *parse_force_inlining_operand(AstFile *f, Token token) {
return ast_bad_expr(f, token, f->curr_token);
}
ProcInlining pi = ProcInlining_none;
+ ProcTailing pt = ProcTailing_none;
if (token.kind == Token_Ident) {
if (token.string == "force_inline") {
pi = ProcInlining_inline;
} else if (token.string == "force_no_inline") {
pi = ProcInlining_no_inline;
+ } else if (token.string == "must_tail") {
+ pt = ProcTailing_must_tail;
}
}
@@ -2211,6 +2214,15 @@ gb_internal Ast *parse_force_inlining_operand(AstFile *f, Token token) {
}
}
+ if (pt != ProcTailing_none) {
+ if (e->kind == Ast_ProcLit) {
+ syntax_error(expr, "'#must_call' can only be applied to a procedure call, not the procedure literal");
+ e->ProcLit.tailing = pt;
+ } else if (e->kind == Ast_CallExpr) {
+ e->CallExpr.tailing = pt;
+ }
+ }
+
return expr;
}
@@ -2507,8 +2519,9 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) {
syntax_error(tag, "#relative types have now been removed in favour of \"core:relative\"");
return ast_relative_type(f, tag, type);
} else if (name.string == "force_inline" ||
- name.string == "force_no_inline") {
- return parse_force_inlining_operand(f, name);
+ name.string == "force_no_inline" ||
+ name.string == "must_tail") {
+ return parse_inlining_or_tailing_operand(f, name);
}
return ast_basic_directive(f, token, name);
}
@@ -4008,6 +4021,10 @@ gb_internal ProcCallingConvention string_to_calling_convention(String const &s)
if (s == "win64") return ProcCC_Win64;
if (s == "sysv") return ProcCC_SysV;
+ if (s == "preserve/none") return ProcCC_PreserveNone;
+ if (s == "preserve/most") return ProcCC_PreserveMost;
+ if (s == "preserve/all") return ProcCC_PreserveAll;
+
if (s == "system") {
if (build_context.metrics.os == TargetOs_windows) {
return ProcCC_StdCall;
@@ -5399,8 +5416,9 @@ gb_internal Ast *parse_stmt(AstFile *f) {
expect_semicolon(f);
return stmt;
} else if (name.string == "force_inline" ||
- name.string == "force_no_inline") {
- Ast *expr = parse_force_inlining_operand(f, name);
+ name.string == "force_no_inline" ||
+ name.string == "must_tail") {
+ Ast *expr = parse_inlining_or_tailing_operand(f, name);
Ast *stmt = ast_expr_stmt(f, expr);
expect_semicolon(f);
return stmt;