aboutsummaryrefslogtreecommitdiff
path: root/src/check_builtin.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2022-08-11 14:30:14 +0100
committergingerBill <bill@gingerbill.org>2022-08-11 14:30:14 +0100
commita7c39060038f63b1840f6eb5c0750bdb47e7d3ea (patch)
tree3ea12b5e4905ec2b571ce8b5564f50ea10c260b7 /src/check_builtin.cpp
parent70dc0c15fd244bdc4a769b0d91b50ecc210bca65 (diff)
`#load(path, type)`
where `type` can be `string` or `[]T` where `T` is a simple type
Diffstat (limited to 'src/check_builtin.cpp')
-rw-r--r--src/check_builtin.cpp49
1 files changed, 42 insertions, 7 deletions
diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp
index 122d3a461..36c9ea001 100644
--- a/src/check_builtin.cpp
+++ b/src/check_builtin.cpp
@@ -1169,11 +1169,11 @@ LoadDirectiveResult check_load_directive(CheckerContext *c, Operand *operand, As
String name = bd->name.string;
GB_ASSERT(name == "load");
- if (ce->args.count != 1) {
+ if (ce->args.count != 1 && ce->args.count != 2) {
if (ce->args.count == 0) {
- error(ce->close, "'#load' expects 1 argument, got 0");
+ error(ce->close, "'#%.*s' expects 1 or 2 arguments, got 0", LIT(name));
} else {
- error(ce->args[0], "'#load' expects 1 argument, got %td", ce->args.count);
+ error(ce->args[0], "'#%.*s' expects 1 or 2 arguments, got %td", LIT(name), ce->args.count);
}
return LoadDirective_Error;
@@ -1183,13 +1183,13 @@ LoadDirectiveResult check_load_directive(CheckerContext *c, Operand *operand, As
Operand o = {};
check_expr(c, &o, arg);
if (o.mode != Addressing_Constant) {
- error(arg, "'#load' expected a constant string argument");
+ error(arg, "'#%.*s' expected a constant string argument", LIT(name));
return LoadDirective_Error;
}
if (!is_type_string(o.type)) {
gbString str = type_to_string(o.type);
- error(arg, "'#load' expected a constant string, got %s", str);
+ error(arg, "'#%.*s' expected a constant string, got %s", LIT(name), str);
gb_string_free(str);
return LoadDirective_Error;
}
@@ -1197,8 +1197,43 @@ LoadDirectiveResult check_load_directive(CheckerContext *c, Operand *operand, As
GB_ASSERT(o.value.kind == ExactValue_String);
operand->type = t_u8_slice;
- if (type_hint && is_type_string(type_hint)) {
- operand->type = type_hint;
+ if (ce->args.count == 1) {
+ if (type_hint && is_type_string(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)) {
+ 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;
+ }
+ }
+
+ 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);
+ }
}
operand->mode = Addressing_Constant;