mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
Allow for chaining of '#load(path) or_else #load(path)'
This commit is contained in:
+29
-27
@@ -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) {
|
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(ce, CallExpr, call);
|
||||||
ast_node(bd, BasicDirective, ce->proc);
|
ast_node(bd, BasicDirective, ce->proc);
|
||||||
@@ -1198,42 +1219,23 @@ LoadDirectiveResult check_load_directive(CheckerContext *c, Operand *operand, As
|
|||||||
|
|
||||||
operand->type = t_u8_slice;
|
operand->type = t_u8_slice;
|
||||||
if (ce->args.count == 1) {
|
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;
|
operand->type = type_hint;
|
||||||
}
|
}
|
||||||
} else if (ce->args.count == 2) {
|
} else if (ce->args.count == 2) {
|
||||||
bool failed = false;
|
|
||||||
Ast *arg_type = ce->args[1];
|
Ast *arg_type = ce->args[1];
|
||||||
Type *type = check_type(c, arg_type);
|
Type *type = check_type(c, arg_type);
|
||||||
if (type != nullptr && type != t_invalid) {
|
if (type != nullptr) {
|
||||||
if (is_type_string(type)) {
|
if (is_valid_type_for_load(type)) {
|
||||||
operand->type = 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 {
|
} 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
if (failed) {
|
GB_PANIC("unreachable");
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
operand->mode = Addressing_Constant;
|
operand->mode = Addressing_Constant;
|
||||||
|
|
||||||
|
|||||||
+29
-26
@@ -7436,36 +7436,39 @@ ExprKind check_or_else_expr(CheckerContext *c, Operand *o, Ast *node, Type *type
|
|||||||
if (is_load_directive_call(arg)) {
|
if (is_load_directive_call(arg)) {
|
||||||
LoadDirectiveResult res = check_load_directive(c, &x, arg, type_hint, false);
|
LoadDirectiveResult res = check_load_directive(c, &x, arg, type_hint, false);
|
||||||
|
|
||||||
bool y_is_diverging = false;
|
// Allow for chaining of '#load(path) or_else #load(path)'
|
||||||
check_expr_base(c, &y, default_value, x.type);
|
if (!(is_load_directive_call(default_value) && res == LoadDirective_Success)) {
|
||||||
switch (y.mode) {
|
bool y_is_diverging = false;
|
||||||
case Addressing_NoValue:
|
check_expr_base(c, &y, default_value, x.type);
|
||||||
if (is_diverging_expr(y.expr)) {
|
switch (y.mode) {
|
||||||
// Allow
|
case Addressing_NoValue:
|
||||||
y.mode = Addressing_Value;
|
if (is_diverging_expr(y.expr)) {
|
||||||
y_is_diverging = true;
|
// Allow
|
||||||
} else {
|
y.mode = Addressing_Value;
|
||||||
error_operand_no_value(&y);
|
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;
|
y.mode = Addressing_Invalid;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case Addressing_Type:
|
|
||||||
error_operand_not_expression(&y);
|
|
||||||
y.mode = Addressing_Invalid;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (y.mode == Addressing_Invalid) {
|
if (y.mode == Addressing_Invalid) {
|
||||||
o->mode = Addressing_Value;
|
o->mode = Addressing_Value;
|
||||||
o->type = t_invalid;
|
o->type = t_invalid;
|
||||||
o->expr = node;
|
o->expr = node;
|
||||||
return Expr_Expr;
|
return Expr_Expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!y_is_diverging) {
|
if (!y_is_diverging) {
|
||||||
check_assignment(c, &y, x.type, name);
|
check_assignment(c, &y, x.type, name);
|
||||||
if (y.mode != Addressing_Constant) {
|
if (y.mode != Addressing_Constant) {
|
||||||
error(y.expr, "expected a constant expression on the right-hand side of 'or_else' in conjuction with '#load'");
|
error(y.expr, "expected a constant expression on the right-hand side of 'or_else' in conjuction with '#load'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user