aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2018-08-09 17:58:11 +0100
committergingerBill <bill@gingerbill.org>2018-08-09 17:58:11 +0100
commit70586b1cf81dcf7940bd39ce7b2c18ed8f0d2aa5 (patch)
treed05b2342675da410c5ffde5e5e36247e4a2cf3d1 /src
parent877a78d6ba2f31ac22278a780f6996eac18f02a4 (diff)
`auto_cast` prefix for procedure parameters
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.cpp17
-rw-r--r--src/check_type.cpp3
-rw-r--r--src/entity.cpp1
-rw-r--r--src/parser.cpp24
-rw-r--r--src/parser.hpp4
5 files changed, 36 insertions, 13 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index c3f252cf7..5427fcd65 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -3879,10 +3879,18 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
i64 s = 0;
if (!check_is_assignable_to_with_score(c, &o, t, &s)) {
- if (show_error) {
- check_assignment(c, &o, t, str_lit("argument"));
+ bool ok = false;
+ if (e->flags & EntityFlag_AutoCast) {
+ ok = check_is_castable_to(c, &o, t);
+ }
+ if (ok) {
+ s = assign_score_function(10);
+ } else {
+ if (show_error) {
+ check_assignment(c, &o, t, str_lit("argument"));
+ }
+ err = CallArgumentError_WrongTypes;
}
- err = CallArgumentError_WrongTypes;
}
score += s;
}
@@ -6107,6 +6115,9 @@ gbString write_expr_to_string(gbString str, Ast *node) {
if (f->flags&FieldFlag_c_vararg) {
str = gb_string_appendc(str, "#c_vararg ");
}
+ if (f->flags&FieldFlag_auto_cast) {
+ str = gb_string_appendc(str, "auto_cast ");
+ }
for_array(i, f->names) {
Ast *name = f->names[i];
diff --git a/src/check_type.cpp b/src/check_type.cpp
index 7e443ff6f..c7417c359 100644
--- a/src/check_type.cpp
+++ b/src/check_type.cpp
@@ -1043,6 +1043,9 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
if (p->flags&FieldFlag_no_alias) {
param->flags |= EntityFlag_NoAlias;
}
+ if (p->flags&FieldFlag_auto_cast) {
+ param->flags |= EntityFlag_AutoCast;
+ }
param->state = EntityState_Resolved; // NOTE(bill): This should have be resolved whilst determining it
add_entity(ctx->checker, scope, name, param);
diff --git a/src/entity.cpp b/src/entity.cpp
index 1374f8c06..ea2f8c119 100644
--- a/src/entity.cpp
+++ b/src/entity.cpp
@@ -47,6 +47,7 @@ enum EntityFlag {
EntityFlag_PolyConst = 1<<13,
EntityFlag_CVarArg = 1<<20,
+ EntityFlag_AutoCast = 1<<21,
};
enum EntityState {
diff --git a/src/parser.cpp b/src/parser.cpp
index 3edc8ba57..30c1797b5 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -2678,6 +2678,7 @@ enum FieldPrefixKind {
FieldPrefix_using,
FieldPrefix_no_alias,
FieldPrefix_c_var_arg,
+ FieldPrefix_auto_cast,
FieldPrefix_in,
};
@@ -2692,6 +2693,9 @@ FieldPrefixKind is_token_field_prefix(AstFile *f) {
case Token_in:
return FieldPrefix_in;
+ case Token_auto_cast:
+ return FieldPrefix_auto_cast;
+
case Token_Hash:
advance_token(f);
switch (f->curr_token.kind) {
@@ -2710,10 +2714,11 @@ FieldPrefixKind is_token_field_prefix(AstFile *f) {
u32 parse_field_prefixes(AstFile *f) {
- i32 using_count = 0;
- i32 no_alias_count = 0;
- i32 c_vararg_count = 0;
- i32 in_count = 0;
+ i32 using_count = 0;
+ i32 no_alias_count = 0;
+ i32 c_vararg_count = 0;
+ i32 in_count = 0;
+ i32 auto_cast_count = 0;
for (;;) {
FieldPrefixKind kind = is_token_field_prefix(f);
@@ -2727,16 +2732,18 @@ u32 parse_field_prefixes(AstFile *f) {
}
switch (kind) {
- case FieldPrefix_using: using_count += 1; advance_token(f); break;
- case FieldPrefix_no_alias: no_alias_count += 1; advance_token(f); break;
- case FieldPrefix_c_var_arg: c_vararg_count += 1; advance_token(f); break;
- case FieldPrefix_in: in_count += 1; advance_token(f); break;
+ case FieldPrefix_using: using_count += 1; advance_token(f); break;
+ case FieldPrefix_no_alias: no_alias_count += 1; advance_token(f); break;
+ case FieldPrefix_c_var_arg: c_vararg_count += 1; advance_token(f); break;
+ case FieldPrefix_in: in_count += 1; advance_token(f); break;
+ case FieldPrefix_auto_cast: auto_cast_count += 1; advance_token(f); break;
}
}
if (using_count > 1) syntax_error(f->curr_token, "Multiple 'using' in this field list");
if (no_alias_count > 1) syntax_error(f->curr_token, "Multiple '#no_alias' in this field list");
if (c_vararg_count > 1) syntax_error(f->curr_token, "Multiple '#c_vararg' in this field list");
if (in_count > 1) syntax_error(f->curr_token, "Multiple 'in' in this field list");
+ if (auto_cast_count > 1) syntax_error(f->curr_token, "Multiple 'auto_cast_count' in this field list");
u32 field_flags = 0;
@@ -2744,6 +2751,7 @@ u32 parse_field_prefixes(AstFile *f) {
if (no_alias_count > 0) field_flags |= FieldFlag_no_alias;
if (c_vararg_count > 0) field_flags |= FieldFlag_c_vararg;
if (in_count > 0) field_flags |= FieldFlag_in;
+ if (auto_cast_count > 0) field_flags |= FieldFlag_auto_cast;
return field_flags;
}
diff --git a/src/parser.hpp b/src/parser.hpp
index a9adee8d3..88d727b33 100644
--- a/src/parser.hpp
+++ b/src/parser.hpp
@@ -177,14 +177,14 @@ enum FieldFlag {
FieldFlag_using = 1<<1,
FieldFlag_no_alias = 1<<2,
FieldFlag_c_vararg = 1<<3,
+ FieldFlag_auto_cast = 1<<4,
FieldFlag_in = 1<<5,
FieldFlag_Results = 1<<16,
- // FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg|FieldFlag_in,
- FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg,
+ FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg|FieldFlag_auto_cast,
FieldFlag_Struct = FieldFlag_using,
};