aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2022-08-11 14:42:29 +0100
committergingerBill <bill@gingerbill.org>2022-08-11 14:42:29 +0100
commitcecadce86d8070ee31d193736d331926efec0fff (patch)
tree185b0bb187ef96bbb5e96defe68ac6994a8393b2 /src
parenta7c39060038f63b1840f6eb5c0750bdb47e7d3ea (diff)
Allow for chaining of '#load(path) or_else #load(path)'
Diffstat (limited to 'src')
-rw-r--r--src/check_builtin.cpp56
-rw-r--r--src/check_expr.cpp55
2 files changed, 58 insertions, 53 deletions
diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp
index 36c9ea001..687f1694b 100644
--- a/src/check_builtin.cpp
+++ b/src/check_builtin.cpp
@@ -1163,6 +1163,27 @@ bool cache_load_file_directive(CheckerContext *c, Ast *call, String const &origi
}
+bool is_valid_type_for_load(Type *type) {
+ if (type == t_invalid) {
+ return false;
+ } else if (is_type_string(type)) {
+ return true;
+ } else if (is_type_slice(type) /*|| is_type_array(type) || is_type_enumerated_array(type)*/) {
+ Type *elem = nullptr;
+ Type *bt = base_type(type);
+ if (bt->kind == Type_Slice) {
+ elem = bt->Slice.elem;
+ } else if (bt->kind == Type_Array) {
+ elem = bt->Array.elem;
+ } else if (bt->kind == Type_EnumeratedArray) {
+ elem = bt->EnumeratedArray.elem;
+ }
+ GB_ASSERT(elem != nullptr);
+ return is_type_load_safe(elem);
+ }
+ return false;
+}
+
LoadDirectiveResult check_load_directive(CheckerContext *c, Operand *operand, Ast *call, Type *type_hint, bool err_on_not_found) {
ast_node(ce, CallExpr, call);
ast_node(bd, BasicDirective, ce->proc);
@@ -1198,42 +1219,23 @@ LoadDirectiveResult check_load_directive(CheckerContext *c, Operand *operand, As
operand->type = t_u8_slice;
if (ce->args.count == 1) {
- if (type_hint && is_type_string(type_hint)) {
+ if (type_hint && is_valid_type_for_load(type_hint)) {
operand->type = type_hint;
}
} else if (ce->args.count == 2) {
- bool failed = false;
Ast *arg_type = ce->args[1];
Type *type = check_type(c, arg_type);
- if (type != nullptr && type != t_invalid) {
- if (is_type_string(type)) {
+ if (type != nullptr) {
+ if (is_valid_type_for_load(type)) {
operand->type = type;
- } else if (is_type_slice(type) /*|| is_type_array(type) || is_type_enumerated_array(type)*/) {
- Type *elem = nullptr;
- Type *bt = base_type(type);
- if (bt->kind == Type_Slice) {
- elem = bt->Slice.elem;
- } else if (bt->kind == Type_Array) {
- elem = bt->Array.elem;
- } else if (bt->kind == Type_EnumeratedArray) {
- elem = bt->EnumeratedArray.elem;
- }
- GB_ASSERT(elem != nullptr);
- if (is_type_load_safe(elem)) {
- operand->type = type;
- } else {
- failed = true;
- }
} else {
- failed = true;
+ gbString type_str = type_to_string(type);
+ error(arg_type, "'#%.*s' invalid type, expected a string, or slice of simple types, got %s", LIT(name), type_str);
+ gb_string_free(type_str);
}
}
-
- if (failed) {
- gbString type_str = type_to_string(type);
- error(arg_type, "'#%.*s' invalid type, expected a string, or slice of simple types, got %s", LIT(name), type_str);
- gb_string_free(type_str);
- }
+ } else {
+ GB_PANIC("unreachable");
}
operand->mode = Addressing_Constant;
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 076eaba73..310874139 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -7436,36 +7436,39 @@ ExprKind check_or_else_expr(CheckerContext *c, Operand *o, Ast *node, Type *type
if (is_load_directive_call(arg)) {
LoadDirectiveResult res = check_load_directive(c, &x, arg, type_hint, false);
- bool y_is_diverging = false;
- check_expr_base(c, &y, default_value, x.type);
- switch (y.mode) {
- case Addressing_NoValue:
- if (is_diverging_expr(y.expr)) {
- // Allow
- y.mode = Addressing_Value;
- y_is_diverging = true;
- } else {
- error_operand_no_value(&y);
+ // Allow for chaining of '#load(path) or_else #load(path)'
+ if (!(is_load_directive_call(default_value) && res == LoadDirective_Success)) {
+ bool y_is_diverging = false;
+ check_expr_base(c, &y, default_value, x.type);
+ switch (y.mode) {
+ case Addressing_NoValue:
+ if (is_diverging_expr(y.expr)) {
+ // Allow
+ y.mode = Addressing_Value;
+ y_is_diverging = true;
+ } else {
+ error_operand_no_value(&y);
+ y.mode = Addressing_Invalid;
+ }
+ break;
+ case Addressing_Type:
+ error_operand_not_expression(&y);
y.mode = Addressing_Invalid;
+ break;
}
- break;
- case Addressing_Type:
- error_operand_not_expression(&y);
- y.mode = Addressing_Invalid;
- break;
- }
- if (y.mode == Addressing_Invalid) {
- o->mode = Addressing_Value;
- o->type = t_invalid;
- o->expr = node;
- return Expr_Expr;
- }
+ if (y.mode == Addressing_Invalid) {
+ o->mode = Addressing_Value;
+ o->type = t_invalid;
+ o->expr = node;
+ return Expr_Expr;
+ }
- if (!y_is_diverging) {
- check_assignment(c, &y, x.type, name);
- if (y.mode != Addressing_Constant) {
- error(y.expr, "expected a constant expression on the right-hand side of 'or_else' in conjuction with '#load'");
+ if (!y_is_diverging) {
+ check_assignment(c, &y, x.type, name);
+ if (y.mode != Addressing_Constant) {
+ error(y.expr, "expected a constant expression on the right-hand side of 'or_else' in conjuction with '#load'");
+ }
}
}