aboutsummaryrefslogtreecommitdiff
path: root/src/check_expr.cpp
diff options
context:
space:
mode:
authorgingerBill <gingerBill@users.noreply.github.com>2020-12-06 00:49:48 +0000
committerGitHub <noreply@github.com>2020-12-06 00:49:48 +0000
commitf0683c910231513db9adab83f7c2fca9dd8d2613 (patch)
tree2539634b5b71caf5148d8927c9298ba20bad5246 /src/check_expr.cpp
parent54fbdabc380905a925ab5e922749fa2b1ccb2621 (diff)
parentca4657fd31b9efc7ab52f7e1b6f4145d5ed28fb7 (diff)
Merge branch 'master' into parser-experiments
Diffstat (limited to 'src/check_expr.cpp')
-rw-r--r--src/check_expr.cpp499
1 files changed, 349 insertions, 150 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 02b54c80a..ea460ce09 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -73,7 +73,7 @@ void update_expr_type (CheckerContext *c, Ast *e, Type *type,
bool check_is_terminating (Ast *node, String const &label);
bool check_has_break (Ast *stmt, String const &label, bool implicit);
void check_stmt (CheckerContext *c, Ast *node, u32 flags);
-void check_stmt_list (CheckerContext *c, Array<Ast *> const &stmts, u32 flags);
+void check_stmt_list (CheckerContext *c, Slice<Ast *> const &stmts, u32 flags);
void check_init_constant (CheckerContext *c, Entity *e, Operand *operand);
bool check_representable_as_constant(CheckerContext *c, ExactValue in_value, Type *type, ExactValue *out_value);
bool check_procedure_type (CheckerContext *c, Type *type, Ast *proc_type_node, Array<Operand> *operands = nullptr);
@@ -89,9 +89,9 @@ Type * check_init_variable (CheckerContext *c, Entity *e, Operand *
Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type, ProcCallingConvention cc);
Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type, ProcCallingConvention cc);
bool abi_compat_return_by_pointer(gbAllocator a, ProcCallingConvention cc, Type *abi_return_type);
-void set_procedure_abi_types(gbAllocator a, Type *type);
+void set_procedure_abi_types(Type *type);
void check_assignment_error_suggestion(CheckerContext *c, Operand *o, Type *type);
-
+void add_map_key_type_dependencies(CheckerContext *ctx, Type *key);
Type *make_soa_struct_slice(CheckerContext *ctx, Ast *array_typ_expr, Ast *elem_expr, Type *elem);
Type *make_soa_struct_dynamic_array(CheckerContext *ctx, Ast *array_typ_expr, Ast *elem_expr, Type *elem);
@@ -133,7 +133,7 @@ void error_operand_no_value(Operand *o) {
}
-void check_scope_decls(CheckerContext *c, Array<Ast *> const &nodes, isize reserve_size) {
+void check_scope_decls(CheckerContext *c, Slice<Ast *> const &nodes, isize reserve_size) {
Scope *s = c->scope;
check_collect_entities(c, nodes);
@@ -267,7 +267,7 @@ bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_enti
CheckerContext nctx = *c;
- Scope *scope = create_scope(base_entity->scope, a);
+ Scope *scope = create_scope(base_entity->scope);
scope->flags |= ScopeFlag_Proc;
nctx.scope = scope;
nctx.allow_polymorphic_types = true;
@@ -366,7 +366,7 @@ bool find_or_generate_polymorphic_procedure(CheckerContext *c, Entity *base_enti
u64 tags = base_entity->Procedure.tags;
Ast *ident = clone_ast(base_entity->identifier);
Token token = ident->Ident.token;
- DeclInfo *d = make_decl_info(nctx.allocator, scope, old_decl->parent);
+ DeclInfo *d = make_decl_info(scope, old_decl->parent);
d->gen_proc_type = final_proc_type;
d->type_expr = pl->type;
d->proc_lit = proc_lit;
@@ -1012,7 +1012,7 @@ bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source,
}
if (modify_type) {
- set_procedure_abi_types(c->allocator, source);
+ set_procedure_abi_types(source);
}
return true;
@@ -1075,8 +1075,10 @@ Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *named_type, Typ
if (e->parent_proc_decl != nullptr &&
e->parent_proc_decl != c->curr_proc_decl) {
if (e->kind == Entity_Variable) {
- error(n, "Nested procedures do not capture its parent's variables: %.*s", LIT(name));
- return nullptr;
+ if ((e->flags & EntityFlag_Static) == 0) {
+ error(n, "Nested procedures do not capture its parent's variables: %.*s", LIT(name));
+ return nullptr;
+ }
} else if (e->kind == Entity_Label) {
error(n, "Nested procedures do not capture its parent's labels: %.*s", LIT(name));
return nullptr;
@@ -1834,10 +1836,6 @@ void check_comparison(CheckerContext *c, Operand *x, Operand *y, TokenKind op) {
gbString err_str = nullptr;
- defer (if (err_str != nullptr) {
- gb_string_free(err_str);
- });
-
if (check_is_assignable_to(c, x, y->type) ||
check_is_assignable_to(c, y, x->type)) {
Type *err_type = x->type;
@@ -1867,8 +1865,8 @@ void check_comparison(CheckerContext *c, Operand *x, Operand *y, TokenKind op) {
}
gbString type_string = type_to_string(err_type);
defer (gb_string_free(type_string));
- err_str = gb_string_make(c->allocator,
- gb_bprintf("operator '%.*s' not defined for type '%s'", LIT(token_strings[op]), type_string));
+ err_str = gb_string_make(temporary_allocator(),
+ gb_bprintf("operator '%.*s' not defined for type '%s'", LIT(token_strings[op]), type_string));
}
} else {
gbString xt, yt;
@@ -1882,8 +1880,7 @@ void check_comparison(CheckerContext *c, Operand *x, Operand *y, TokenKind op) {
} else {
yt = type_to_string(y->type);
}
- err_str = gb_string_make(c->allocator,
- gb_bprintf("mismatched types '%s' and '%s'", xt, yt));
+ err_str = gb_string_make(temporary_allocator(), gb_bprintf("mismatched types '%s' and '%s'", xt, yt));
gb_string_free(yt);
gb_string_free(xt);
}
@@ -2166,6 +2163,17 @@ bool check_is_castable_to(CheckerContext *c, Operand *operand, Type *y) {
return true;
}
+ if (is_constant && is_type_untyped(src) && is_type_string(src)) {
+ if (is_type_u8_array(dst)) {
+ String s = operand->value.value_string;
+ return s.len == dst->Array.count;
+ }
+ if (is_type_rune_array(dst)) {
+ String s = operand->value.value_string;
+ return gb_utf8_strnlen(s.text, s.len) == dst->Array.count;
+ }
+ }
+
if (dst->kind == Type_Array && src->kind == Type_Array) {
if (are_types_identical(dst->Array.elem, src->Array.elem)) {
@@ -2960,6 +2968,19 @@ void convert_to_typed(CheckerContext *c, Operand *operand, Type *target_type) {
if (check_is_assignable_to(c, operand, elem)) {
operand->mode = Addressing_Value;
} else {
+ if (operand->value.kind == ExactValue_String) {
+ String s = operand->value.value_string;
+ if (is_type_u8_array(t)) {
+ if (s.len == t->Array.count) {
+ break;
+ }
+ } else if (is_type_rune_array(t)) {
+ isize rune_count = gb_utf8_strnlen(s.text, s.len);
+ if (rune_count == t->Array.count) {
+ break;
+ }
+ }
+ }
operand->mode = Addressing_Invalid;
convert_untyped_error(c, operand, target_type);
return;
@@ -2979,8 +3000,7 @@ void convert_to_typed(CheckerContext *c, Operand *operand, Type *target_type) {
case Type_Union:
if (!is_operand_nil(*operand) && !is_operand_undef(*operand)) {
isize count = t->Union.variants.count;
- ValidIndexAndScore *valids = gb_alloc_array(c->allocator, ValidIndexAndScore, count);
- defer (gb_free(c->allocator, valids));
+ ValidIndexAndScore *valids = gb_alloc_array(temporary_allocator(), ValidIndexAndScore, count);
isize valid_count = 0;
isize first_success_index = -1;
for_array(i, t->Union.variants) {
@@ -3389,7 +3409,7 @@ ExactValue get_constant_field(CheckerContext *c, Operand const *operand, Selecti
return value;
} else if (value.kind == ExactValue_Quaternion) {
// @QuaternionLayout
- Quaternion256 q = value.value_quaternion;
+ Quaternion256 q = *value.value_quaternion;
GB_ASSERT(sel.index.count == 1);
switch (sel.index[0]) {
@@ -3414,7 +3434,7 @@ ExactValue get_constant_field(CheckerContext *c, Operand const *operand, Selecti
return empty_exact_value;
} else if (value.kind == ExactValue_Complex) {
// @QuaternionLayout
- Complex128 c = value.value_complex;
+ Complex128 c = *value.value_complex;
GB_ASSERT(sel.index.count == 1);
switch (sel.index[0]) {
@@ -3443,6 +3463,13 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ
Entity *entity = nullptr;
Selection sel = {}; // NOTE(bill): Not used if it's an import name
+ if (!c->allow_arrow_right_selector_expr && se->token.kind == Token_ArrowRight) {
+ error(node, "Illegal use of -> selector shorthand outside of a call");
+ operand->mode = Addressing_Invalid;
+ operand->expr = node;
+ return nullptr;
+ }
+
operand->expr = node;
Ast *op_expr = se->expr;
@@ -4343,7 +4370,6 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
add_type_info_type(c, t);
- t = base_type(t);
if (o.mode != Addressing_Type) {
error(expr, "Expected a type for 'typeid_of'");
return false;
@@ -4351,6 +4377,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
operand->mode = Addressing_Value;
operand->type = t_typeid;
+ operand->value = exact_value_typeid(t);
break;
}
@@ -4702,8 +4729,8 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
if (is_type_complex(x->type)) {
if (x->mode == Addressing_Constant) {
ExactValue v = exact_value_to_complex(x->value);
- f64 r = v.value_complex.real;
- f64 i = -v.value_complex.imag;
+ f64 r = v.value_complex->real;
+ f64 i = -v.value_complex->imag;
x->value = exact_value_complex(r, i);
x->mode = Addressing_Constant;
} else {
@@ -4712,10 +4739,10 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
} else if (is_type_quaternion(x->type)) {
if (x->mode == Addressing_Constant) {
ExactValue v = exact_value_to_quaternion(x->value);
- f64 r = v.value_quaternion.real;
- f64 i = -v.value_quaternion.imag;
- f64 j = -v.value_quaternion.jmag;
- f64 k = -v.value_quaternion.kmag;
+ f64 r = +v.value_quaternion->real;
+ f64 i = -v.value_quaternion->imag;
+ f64 j = -v.value_quaternion->jmag;
+ f64 k = -v.value_quaternion->kmag;
x->value = exact_value_quaternion(r, i, j, k);
x->mode = Addressing_Constant;
} else {
@@ -4739,7 +4766,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
gb_string_free(type_str);
return false;
}
- gbAllocator a = c->allocator;
+ gbAllocator a = permanent_allocator();
Type *tuple = alloc_type_tuple();
@@ -5132,8 +5159,8 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
operand->value.value_float = gb_abs(operand->value.value_float);
break;
case ExactValue_Complex: {
- f64 r = operand->value.value_complex.real;
- f64 i = operand->value.value_complex.imag;
+ f64 r = operand->value.value_complex->real;
+ f64 i = operand->value.value_complex->imag;
operand->value = exact_value_float(gb_sqrt(r*r + i*i));
break;
@@ -5356,7 +5383,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
soa_struct->Struct.soa_elem = elem;
soa_struct->Struct.soa_count = count;
- scope = create_scope(c->scope, c->allocator);
+ scope = create_scope(c->scope);
soa_struct->Struct.scope = scope;
String params_xyzw[4] = {
@@ -5389,7 +5416,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
soa_struct->Struct.soa_elem = elem;
soa_struct->Struct.soa_count = count;
- scope = create_scope(old_struct->Struct.scope->parent, c->allocator);
+ scope = create_scope(old_struct->Struct.scope->parent);
soa_struct->Struct.scope = scope;
for_array(i, old_struct->Struct.fields) {
@@ -6035,6 +6062,50 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
break;
}
break;
+
+ case BuiltinProc_type_equal_proc:
+ {
+ Operand op = {};
+ Type *bt = check_type(c, ce->args[0]);
+ Type *type = base_type(bt);
+ if (type == nullptr || type == t_invalid) {
+ error(ce->args[0], "Expected a type for '%.*s'", LIT(builtin_name));
+ return false;
+ }
+ if (!is_type_comparable(type)) {
+ gbString t = type_to_string(type);
+ error(ce->args[0], "Expected a comparable type for '%.*s', got %s", LIT(builtin_name), t);
+ gb_string_free(t);
+ return false;
+ }
+
+ operand->mode = Addressing_Value;
+ operand->type = t_equal_proc;
+ break;
+ }
+
+ case BuiltinProc_type_hasher_proc:
+ {
+ Operand op = {};
+ Type *bt = check_type(c, ce->args[0]);
+ Type *type = base_type(bt);
+ if (type == nullptr || type == t_invalid) {
+ error(ce->args[0], "Expected a type for '%.*s'", LIT(builtin_name));
+ return false;
+ }
+ if (!is_type_valid_for_keys(type)) {
+ gbString t = type_to_string(type);
+ error(ce->args[0], "Expected a valid type for map keys for '%.*s', got %s", LIT(builtin_name), t);
+ gb_string_free(t);
+ return false;
+ }
+
+ add_map_key_type_dependencies(c, type);
+
+ operand->mode = Addressing_Value;
+ operand->type = t_hasher_proc;
+ break;
+ }
}
return true;
@@ -6061,7 +6132,7 @@ isize add_dependencies_from_unpacking(CheckerContext *c, Entity **lhs, isize lhs
}
-bool check_assignment_arguments(CheckerContext *ctx, Array<Operand> const &lhs, Array<Operand> *operands, Array<Ast *> const &rhs) {
+bool check_assignment_arguments(CheckerContext *ctx, Array<Operand> const &lhs, Array<Operand> *operands, Slice<Ast *> const &rhs) {
bool optional_ok = false;
isize tuple_index = 0;
for_array(i, rhs) {
@@ -6145,7 +6216,7 @@ bool check_assignment_arguments(CheckerContext *ctx, Array<Operand> const &lhs,
-bool check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize lhs_count, Array<Operand> *operands, Array<Ast *> const &rhs, bool allow_ok, bool is_variadic) {
+bool check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize lhs_count, Array<Operand> *operands, Slice<Ast *> const &rhs, bool allow_ok, bool is_variadic) {
bool optional_ok = false;
isize tuple_index = 0;
for_array(i, rhs) {
@@ -6540,10 +6611,8 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
CallArgumentError err = CallArgumentError_None;
isize param_count = pt->param_count;
- bool *visited = gb_alloc_array(c->allocator, bool, param_count);
- defer (gb_free(c->allocator, visited));
- auto ordered_operands = array_make<Operand>(c->allocator, param_count);
- defer (array_free(&ordered_operands));
+ bool *visited = gb_alloc_array(temporary_allocator(), bool, param_count);
+ auto ordered_operands = array_make<Operand>(temporary_allocator(), param_count);
defer ({
for_array(i, ordered_operands) {
Operand const &o = ordered_operands[i];
@@ -6749,7 +6818,7 @@ Entity **populate_proc_parameter_list(CheckerContext *c, Type *proc_type, isize
}
-bool evaluate_where_clauses(CheckerContext *ctx, Ast *call_expr, Scope *scope, Array<Ast *> *clauses, bool print_err) {
+bool evaluate_where_clauses(CheckerContext *ctx, Ast *call_expr, Scope *scope, Slice<Ast *> *clauses, bool print_err) {
if (clauses != nullptr) {
for_array(i, *clauses) {
Ast *clause = (*clauses)[i];
@@ -6814,7 +6883,7 @@ bool evaluate_where_clauses(CheckerContext *ctx, Ast *call_expr, Scope *scope, A
}
-CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type *proc_type, Ast *call, Array<Ast *> const &args) {
+CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type *proc_type, Ast *call, Slice<Ast *> const &args) {
ast_node(ce, CallExpr, call);
CallArgumentCheckerType *call_checker = check_call_arguments_internal;
@@ -7338,6 +7407,7 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
Entity *e = params->variables[i];
if (e->kind == Entity_Constant) {
check_expr_with_type_hint(c, &operands[i], fv->value, e->type);
+ continue;
}
}
@@ -7371,13 +7441,26 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
TypeTuple *tuple = get_record_polymorphic_params(original_type);
isize param_count = tuple->variables.count;
+ isize minimum_param_count = param_count;
+ for (minimum_param_count = tuple->variables.count-1; minimum_param_count >= 0; minimum_param_count--) {
+ Entity *e = tuple->variables[minimum_param_count];
+ if (e->kind != Entity_Constant) {
+ break;
+ }
+ if (e->Constant.param_value.kind == ParameterValue_Invalid) {
+ break;
+ }
+ }
Array<Operand> ordered_operands = operands;
- if (named_fields) {
- bool *visited = gb_alloc_array(c->allocator, bool, param_count);
+ if (!named_fields) {
+ ordered_operands = array_make<Operand>(permanent_allocator(), param_count);
+ array_copy(&ordered_operands, operands, 0);
+ } else {
+ bool *visited = gb_alloc_array(temporary_allocator(), bool, param_count);
// LEAK(bill)
- ordered_operands = array_make<Operand>(c->allocator, param_count);
+ ordered_operands = array_make<Operand>(permanent_allocator(), param_count);
for_array(i, ce->args) {
Ast *arg = ce->args[i];
@@ -7440,26 +7523,55 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
return err;
}
- if (param_count < ordered_operands.count) {
- error(call, "Too many polymorphic type arguments, expected %td, got %td", param_count, ordered_operands.count);
- err = CallArgumentError_TooManyArguments;
- } else if (param_count > ordered_operands.count) {
- error(call, "Too few polymorphic type arguments, expected %td, got %td", param_count, ordered_operands.count);
- err = CallArgumentError_TooFewArguments;
+ if (minimum_param_count != param_count) {
+ if (param_count < ordered_operands.count) {
+ error(call, "Too many polymorphic type arguments, expected a maximum of %td, got %td", param_count, ordered_operands.count);
+ err = CallArgumentError_TooManyArguments;
+ } else if (minimum_param_count > ordered_operands.count) {
+ error(call, "Too few polymorphic type arguments, expected a minimum of %td, got %td", minimum_param_count, ordered_operands.count);
+ err = CallArgumentError_TooFewArguments;
+ }
+ } else {
+ if (param_count < ordered_operands.count) {
+ error(call, "Too many polymorphic type arguments, expected %td, got %td", param_count, ordered_operands.count);
+ err = CallArgumentError_TooManyArguments;
+ } else if (param_count > ordered_operands.count) {
+ error(call, "Too few polymorphic type arguments, expected %td, got %td", param_count, ordered_operands.count);
+ err = CallArgumentError_TooFewArguments;
+ }
}
if (err != 0) {
return err;
}
+ if (minimum_param_count != param_count) {
+ isize missing_count = 0;
+ // NOTE(bill): Replace missing operands with the default values (if possible)
+ for_array(i, ordered_operands) {
+ Operand *o = &ordered_operands[i];
+ if (o->expr == nullptr) {
+ Entity *e = tuple->variables[i];
+ if (e->kind == Entity_Constant) {
+ missing_count += 1;
+ o->mode = Addressing_Constant;
+ o->type = default_type(e->type);
+ o->expr = unparen_expr(e->Constant.param_value.original_ast_expr);
+ if (e->Constant.param_value.kind == ParameterValue_Constant) {
+ o->value = e->Constant.param_value.value;
+ }
+ }
+ }
+ }
+ }
+
i64 score = 0;
for (isize i = 0; i < param_count; i++) {
+ Entity *e = tuple->variables[i];
Operand *o = &ordered_operands[i];
if (o->mode == Addressing_Invalid) {
continue;
}
- Entity *e = tuple->variables[i];
-
if (e->kind == Entity_TypeName) {
if (o->mode != Addressing_Type) {
if (show_error) {
@@ -7506,8 +7618,6 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
}
{
- gbAllocator a = c->allocator;
-
bool failure = false;
Entity *found_entity = find_polymorphic_record_entity(c, original_type, param_count, ordered_operands, &failure);
if (found_entity) {
@@ -7558,7 +7668,7 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
-ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call, Ast *proc, Array<Ast *> const &args, ProcInlining inlining, Type *type_hint) {
+ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call, Ast *proc, Slice<Ast *> const &args, ProcInlining inlining, Type *type_hint) {
if (proc != nullptr &&
proc->kind == Ast_BasicDirective) {
ast_node(bd, BasicDirective, proc);
@@ -7595,7 +7705,7 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call, Ast *pr
mix = arg->kind == Ast_FieldValue;
}
if (mix) {
- error(arg, "Mixture of 'field = value' and value elements in a procedure all is not allowed");
+ error(arg, "Mixture of 'field = value' and value elements in a procedure call is not allowed");
fail = true;
}
}
@@ -7800,7 +7910,7 @@ void check_expr_with_type_hint(CheckerContext *c, Operand *o, Ast *e, Type *t) {
err_str = "used as a value";
break;
case Addressing_Type:
- err_str = "is not an expression";
+ err_str = "is not an expression but a type";
break;
case Addressing_Builtin:
err_str = "must be called";
@@ -8110,7 +8220,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
case_ast_node(bl, BasicLit, node);
Type *t = t_invalid;
- switch (bl->value.kind) {
+ switch (node->tav.value.kind) {
case ExactValue_String: t = t_untyped_string; break;
case ExactValue_Float: t = t_untyped_float; break;
case ExactValue_Complex: t = t_untyped_complex; break;
@@ -8128,7 +8238,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
o->mode = Addressing_Constant;
o->type = t;
- o->value = bl->value;
+ o->value = node->tav.value;
case_end;
case_ast_node(bd, BasicDirective, node);
@@ -8170,7 +8280,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
Type *type = alloc_type(Type_Proc);
check_open_scope(&ctx, pl->type);
{
- decl = make_decl_info(ctx.allocator, ctx.scope, ctx.decl);
+ decl = make_decl_info(ctx.scope, ctx.decl);
decl->proc_lit = node;
ctx.decl = decl;
defer (ctx.decl = ctx.decl->parent);
@@ -8467,7 +8577,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
}
if (cl->elems[0]->kind == Ast_FieldValue) {
- bool *fields_visited = gb_alloc_array(c->allocator, bool, field_count);
+ bool *fields_visited = gb_alloc_array(temporary_allocator(), bool, field_count);
for_array(i, cl->elems) {
Ast *elem = cl->elems[i];
@@ -9065,6 +9175,9 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
}
is_constant = false;
{ // Checker values
+ bool key_is_typeid = is_type_typeid(t->Map.key);
+ bool value_is_typeid = is_type_typeid(t->Map.value);
+
for_array(i, cl->elems) {
Ast *elem = cl->elems[i];
if (elem->kind != Ast_FieldValue) {
@@ -9072,13 +9185,22 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
continue;
}
ast_node(fv, FieldValue, elem);
- check_expr_with_type_hint(c, o, fv->field, t->Map.key);
+
+ if (key_is_typeid) {
+ check_expr_or_type(c, o, fv->field, t->Map.key);
+ } else {
+ check_expr_with_type_hint(c, o, fv->field, t->Map.key);
+ }
check_assignment(c, o, t->Map.key, str_lit("map literal"));
if (o->mode == Addressing_Invalid) {
continue;
}
- check_expr_with_type_hint(c, o, fv->value, t->Map.value);
+ if (value_is_typeid) {
+ check_expr_or_type(c, o, fv->value, t->Map.value);
+ } else {
+ check_expr_with_type_hint(c, o, fv->value, t->Map.value);
+ }
check_assignment(c, o, t->Map.value, str_lit("map literal"));
}
}
@@ -9349,6 +9471,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
}
add_package_dependency(c, "runtime", "type_assertion_check");
+ add_package_dependency(c, "runtime", "type_assertion_check2");
case_end;
case_ast_node(tc, TypeCast, node);
@@ -9447,8 +9570,13 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
//
// NOTE(bill, 2020-05-22): I'm going to regret this decision, ain't I?
+ bool allow_arrow_right_selector_expr;
+ allow_arrow_right_selector_expr = c->allow_arrow_right_selector_expr;
+ c->allow_arrow_right_selector_expr = true;
Operand x = {};
ExprKind kind = check_expr_base(c, &x, se->expr, nullptr);
+ c->allow_arrow_right_selector_expr = allow_arrow_right_selector_expr;
+
if (x.mode == Addressing_Invalid || x.type == t_invalid) {
o->mode = Addressing_Invalid;
o->type = t_invalid;
@@ -9543,13 +9671,17 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
- auto modified_args = array_make<Ast *>(heap_allocator(), ce->args.count+1);
+ auto modified_args = slice_make<Ast *>(heap_allocator(), ce->args.count+1);
modified_args[0] = first_arg;
- array_copy(&modified_args, ce->args, 1);
+ slice_copy(&modified_args, ce->args, 1);
ce->args = modified_args;
se->modified_call = true;
+ allow_arrow_right_selector_expr = c->allow_arrow_right_selector_expr;
+ c->allow_arrow_right_selector_expr = true;
check_expr_base(c, o, se->call, type_hint);
+ c->allow_arrow_right_selector_expr = allow_arrow_right_selector_expr;
+
o->expr = node;
return Expr_Expr;
case_end;
@@ -9634,7 +9766,11 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
if (is_type_map(t)) {
Operand key = {};
- check_expr_with_type_hint(c, &key, ie->index, t->Map.key);
+ if (is_type_typeid(t->Map.key)) {
+ check_expr_or_type(c, &key, ie->index, t->Map.key);
+ } else {
+ check_expr_with_type_hint(c, &key, ie->index, t->Map.key);
+ }
check_assignment(c, &key, t->Map.key, str_lit("map index"));
if (key.mode == Addressing_Invalid) {
o->mode = Addressing_Invalid;
@@ -10033,7 +10169,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
error(x.expr, "Expected a constant string for the inline asm constraints parameter");
}
- Scope *scope = create_scope(c->scope, heap_allocator());
+ Scope *scope = create_scope(c->scope);
scope->flags |= ScopeFlag_Proc;
Type *params = alloc_type_tuple();
@@ -10143,14 +10279,14 @@ void check_expr_or_type(CheckerContext *c, Operand *o, Ast *e, Type *type_hint)
}
-gbString write_expr_to_string(gbString str, Ast *node);
+gbString write_expr_to_string(gbString str, Ast *node, bool shorthand);
-gbString write_struct_fields_to_string(gbString str, Array<Ast *> const &params) {
+gbString write_struct_fields_to_string(gbString str, Slice<Ast *> const &params) {
for_array(i, params) {
if (i > 0) {
str = gb_string_appendc(str, ", ");
}
- str = write_expr_to_string(str, params[i]);
+ str = write_expr_to_string(str, params[i], false);
}
return str;
}
@@ -10164,11 +10300,23 @@ gbString string_append_string(gbString str, String string) {
gbString string_append_token(gbString str, Token token) {
- return string_append_string(str, token.string);
+ if (token.kind == Token_String) {
+ str = gb_string_append_rune(str, '"');
+ } else if (token.kind == Token_Rune) {
+ str = gb_string_append_rune(str, '\'');
+ }
+ str = string_append_string(str, token.string);
+ if (token.kind == Token_String) {
+ str = gb_string_append_rune(str, '"');
+ } else if (token.kind == Token_Rune) {
+ str = gb_string_append_rune(str, '\'');
+ }
+
+ return str;
}
-gbString write_expr_to_string(gbString str, Ast *node) {
+gbString write_expr_to_string(gbString str, Ast *node, bool shorthand) {
if (node == nullptr)
return str;
@@ -10206,21 +10354,30 @@ gbString write_expr_to_string(gbString str, Ast *node) {
str = gb_string_appendc(str, "proc{");
for_array(i, pg->args) {
if (i > 0) str = gb_string_appendc(str, ", ");
- str = write_expr_to_string(str, pg->args[i]);
+ str = write_expr_to_string(str, pg->args[i], shorthand);
}
str = gb_string_append_rune(str, '}');
case_end;
case_ast_node(pl, ProcLit, node);
- str = write_expr_to_string(str, pl->type);
+ str = write_expr_to_string(str, pl->type, shorthand);
+ if (pl->body) {
+ str = gb_string_appendc(str, " {...}");
+ } else {
+ str = gb_string_appendc(str, " ---");
+ }
case_end;
case_ast_node(cl, CompoundLit, node);
- str = write_expr_to_string(str, cl->type);
+ str = write_expr_to_string(str, cl->type, shorthand);
str = gb_string_append_rune(str, '{');
- for_array(i, cl->elems) {
- if (i > 0) str = gb_string_appendc(str, ", ");
- str = write_expr_to_string(str, cl->elems[i]);
+ if (shorthand) {
+ str = gb_string_appendc(str, "...");
+ } else {
+ for_array(i, cl->elems) {
+ if (i > 0) str = gb_string_appendc(str, ", ");
+ str = write_expr_to_string(str, cl->elems[i], shorthand);
+ }
}
str = gb_string_append_rune(str, '}');
case_end;
@@ -10229,71 +10386,71 @@ gbString write_expr_to_string(gbString str, Ast *node) {
case_ast_node(te, TagExpr, node);
str = gb_string_append_rune(str, '#');
str = string_append_token(str, te->name);
- str = write_expr_to_string(str, te->expr);
+ str = write_expr_to_string(str, te->expr, shorthand);
case_end;
case_ast_node(ue, UnaryExpr, node);
str = string_append_token(str, ue->op);
- str = write_expr_to_string(str, ue->expr);
+ str = write_expr_to_string(str, ue->expr, shorthand);
case_end;
case_ast_node(de, DerefExpr, node);
- str = write_expr_to_string(str, de->expr);
+ str = write_expr_to_string(str, de->expr, shorthand);
str = gb_string_append_rune(str, '^');
case_end;
case_ast_node(be, BinaryExpr, node);
- str = write_expr_to_string(str, be->left);
+ str = write_expr_to_string(str, be->left, shorthand);
str = gb_string_append_rune(str, ' ');
str = string_append_token(str, be->op);
str = gb_string_append_rune(str, ' ');
- str = write_expr_to_string(str, be->right);
+ str = write_expr_to_string(str, be->right, shorthand);
case_end;
case_ast_node(te, TernaryExpr, node);
- str = write_expr_to_string(str, te->cond);
+ str = write_expr_to_string(str, te->cond, shorthand);
str = gb_string_appendc(str, " ? ");
- str = write_expr_to_string(str, te->x);
+ str = write_expr_to_string(str, te->x, shorthand);
str = gb_string_appendc(str, " : ");
- str = write_expr_to_string(str, te->y);
+ str = write_expr_to_string(str, te->y, shorthand);
case_end;
case_ast_node(te, TernaryIfExpr, node);
- str = write_expr_to_string(str, te->x);
+ str = write_expr_to_string(str, te->x, shorthand);
str = gb_string_appendc(str, " if ");
- str = write_expr_to_string(str, te->cond);
+ str = write_expr_to_string(str, te->cond, shorthand);
str = gb_string_appendc(str, " else ");
- str = write_expr_to_string(str, te->y);
+ str = write_expr_to_string(str, te->y, shorthand);
case_end;
case_ast_node(te, TernaryWhenExpr, node);
- str = write_expr_to_string(str, te->x);
+ str = write_expr_to_string(str, te->x, shorthand);
str = gb_string_appendc(str, " when ");
- str = write_expr_to_string(str, te->cond);
+ str = write_expr_to_string(str, te->cond, shorthand);
str = gb_string_appendc(str, " else ");
- str = write_expr_to_string(str, te->y);
+ str = write_expr_to_string(str, te->y, shorthand);
case_end;
case_ast_node(pe, ParenExpr, node);
str = gb_string_append_rune(str, '(');
- str = write_expr_to_string(str, pe->expr);
+ str = write_expr_to_string(str, pe->expr, shorthand);
str = gb_string_append_rune(str, ')');
case_end;
case_ast_node(se, SelectorExpr, node);
- str = write_expr_to_string(str, se->expr);
+ str = write_expr_to_string(str, se->expr, shorthand);
str = string_append_token(str, se->token);
- str = write_expr_to_string(str, se->selector);
+ str = write_expr_to_string(str, se->selector, shorthand);
case_end;
case_ast_node(se, ImplicitSelectorExpr, node);
str = gb_string_append_rune(str, '.');
- str = write_expr_to_string(str, se->selector);
+ str = write_expr_to_string(str, se->selector, shorthand);
case_end;
case_ast_node(se, SelectorCallExpr, node);
- str = write_expr_to_string(str, se->expr);
+ str = write_expr_to_string(str, se->expr, shorthand);
str = gb_string_appendc(str, "(");
ast_node(ce, CallExpr, se->call);
isize start = se->modified_call ? 1 : 0;
@@ -10302,86 +10459,86 @@ gbString write_expr_to_string(gbString str, Ast *node) {
if (i > start) {
str = gb_string_appendc(str, ", ");
}
- str = write_expr_to_string(str, arg);
+ str = write_expr_to_string(str, arg, shorthand);
}
str = gb_string_appendc(str, ")");
case_end;
case_ast_node(ta, TypeAssertion, node);
- str = write_expr_to_string(str, ta->expr);
+ str = write_expr_to_string(str, ta->expr, shorthand);
str = gb_string_appendc(str, ".(");
- str = write_expr_to_string(str, ta->type);
+ str = write_expr_to_string(str, ta->type, shorthand);
str = gb_string_append_rune(str, ')');
case_end;
case_ast_node(tc, TypeCast, node);
str = string_append_token(str, tc->token);
str = gb_string_append_rune(str, '(');
- str = write_expr_to_string(str, tc->type);
+ str = write_expr_to_string(str, tc->type, shorthand);
str = gb_string_append_rune(str, ')');
- str = write_expr_to_string(str, tc->expr);
+ str = write_expr_to_string(str, tc->expr, shorthand);
case_end;
case_ast_node(ac, AutoCast, node);
str = string_append_token(str, ac->token);
str = gb_string_append_rune(str, ' ');
- str = write_expr_to_string(str, ac->expr);
+ str = write_expr_to_string(str, ac->expr, shorthand);
case_end;
case_ast_node(ie, IndexExpr, node);
- str = write_expr_to_string(str, ie->expr);
+ str = write_expr_to_string(str, ie->expr, shorthand);
str = gb_string_append_rune(str, '[');
- str = write_expr_to_string(str, ie->index);
+ str = write_expr_to_string(str, ie->index, shorthand);
str = gb_string_append_rune(str, ']');
case_end;
case_ast_node(se, SliceExpr, node);
- str = write_expr_to_string(str, se->expr);
+ str = write_expr_to_string(str, se->expr, shorthand);
str = gb_string_append_rune(str, '[');
- str = write_expr_to_string(str, se->low);
+ str = write_expr_to_string(str, se->low, shorthand);
str = string_append_token(str, se->interval);
- str = write_expr_to_string(str, se->high);
+ str = write_expr_to_string(str, se->high, shorthand);
str = gb_string_append_rune(str, ']');
case_end;
case_ast_node(e, Ellipsis, node);
str = gb_string_appendc(str, "..");
- str = write_expr_to_string(str, e->expr);
+ str = write_expr_to_string(str, e->expr, shorthand);
case_end;
case_ast_node(fv, FieldValue, node);
- str = write_expr_to_string(str, fv->field);
+ str = write_expr_to_string(str, fv->field, shorthand);
str = gb_string_appendc(str, " = ");
- str = write_expr_to_string(str, fv->value);
+ str = write_expr_to_string(str, fv->value, shorthand);
case_end;
case_ast_node(ht, HelperType, node);
str = gb_string_appendc(str, "#type ");
- str = write_expr_to_string(str, ht->type);
+ str = write_expr_to_string(str, ht->type, shorthand);
case_end;
case_ast_node(ht, DistinctType, node);
str = gb_string_appendc(str, "distinct ");
- str = write_expr_to_string(str, ht->type);
+ str = write_expr_to_string(str, ht->type, shorthand);
case_end;
case_ast_node(ht, OpaqueType, node);
str = gb_string_appendc(str, "opaque ");
- str = write_expr_to_string(str, ht->type);
+ str = write_expr_to_string(str, ht->type, shorthand);
case_end;
case_ast_node(pt, PolyType, node);
str = gb_string_append_rune(str, '$');
- str = write_expr_to_string(str, pt->type);
+ str = write_expr_to_string(str, pt->type, shorthand);
if (pt->specialization != nullptr) {
str = gb_string_append_rune(str, '/');
- str = write_expr_to_string(str, pt->specialization);
+ str = write_expr_to_string(str, pt->specialization, shorthand);
}
case_end;
case_ast_node(pt, PointerType, node);
str = gb_string_append_rune(str, '^');
- str = write_expr_to_string(str, pt->type);
+ str = write_expr_to_string(str, pt->type, shorthand);
case_end;
case_ast_node(at, ArrayType, node);
@@ -10391,40 +10548,44 @@ gbString write_expr_to_string(gbString str, Ast *node) {
at->count->UnaryExpr.op.kind == Token_Question) {
str = gb_string_appendc(str, "?");
} else {
- str = write_expr_to_string(str, at->count);
+ str = write_expr_to_string(str, at->count, shorthand);
}
str = gb_string_append_rune(str, ']');
- str = write_expr_to_string(str, at->elem);
+ str = write_expr_to_string(str, at->elem, shorthand);
case_end;
case_ast_node(at, DynamicArrayType, node);
str = gb_string_appendc(str, "[dynamic]");
- str = write_expr_to_string(str, at->elem);
+ str = write_expr_to_string(str, at->elem, shorthand);
case_end;
case_ast_node(bf, BitFieldType, node);
str = gb_string_appendc(str, "bit_field ");
if (bf->align) {
str = gb_string_appendc(str, "#align ");
- str = write_expr_to_string(str, bf->align);
+ str = write_expr_to_string(str, bf->align, shorthand);
}
str = gb_string_appendc(str, "{");
- str = write_struct_fields_to_string(str, bf->fields);
+ if (shorthand) {
+ str = gb_string_appendc(str, "...");
+ } else {
+ str = write_struct_fields_to_string(str, bf->fields);
+ }
str = gb_string_appendc(str, "}");
case_end;
case_ast_node(bs, BitSetType, node);
str = gb_string_appendc(str, "bit_set[");
- str = write_expr_to_string(str, bs->elem);
+ str = write_expr_to_string(str, bs->elem, shorthand);
str = gb_string_appendc(str, "]");
case_end;
case_ast_node(mt, MapType, node);
str = gb_string_appendc(str, "map[");
- str = write_expr_to_string(str, mt->key);
+ str = write_expr_to_string(str, mt->key, shorthand);
str = gb_string_append_rune(str, ']');
- str = write_expr_to_string(str, mt->value);
+ str = write_expr_to_string(str, mt->value, shorthand);
case_end;
case_ast_node(f, Field, node);
@@ -10444,7 +10605,7 @@ gbString write_expr_to_string(gbString str, Ast *node) {
for_array(i, f->names) {
Ast *name = f->names[i];
if (i > 0) str = gb_string_appendc(str, ", ");
- str = write_expr_to_string(str, name);
+ str = write_expr_to_string(str, name, shorthand);
}
if (f->names.count > 0) {
if (f->type == nullptr && f->default_value != nullptr) {
@@ -10454,14 +10615,14 @@ gbString write_expr_to_string(gbString str, Ast *node) {
}
if (f->type != nullptr) {
str = gb_string_append_rune(str, ' ');
- str = write_expr_to_string(str, f->type);
+ str = write_expr_to_string(str, f->type, shorthand);
}
if (f->default_value != nullptr) {
if (f->type != nullptr) {
str = gb_string_append_rune(str, ' ');
}
str = gb_string_appendc(str, "= ");
- str = write_expr_to_string(str, f->default_value);
+ str = write_expr_to_string(str, f->default_value, shorthand);
}
case_end;
@@ -10487,7 +10648,7 @@ gbString write_expr_to_string(gbString str, Ast *node) {
for_array(i, f->list) {
if (i > 0) str = gb_string_appendc(str, ", ");
if (has_name) {
- str = write_expr_to_string(str, f->list[i]);
+ str = write_expr_to_string(str, f->list[i], shorthand);
} else {
ast_node(field, Field, f->list[i]);
@@ -10501,7 +10662,7 @@ gbString write_expr_to_string(gbString str, Ast *node) {
str = gb_string_appendc(str, "#c_vararg ");
}
- str = write_expr_to_string(str, field->type);
+ str = write_expr_to_string(str, field->type, shorthand);
}
}
case_end;
@@ -10516,7 +10677,7 @@ gbString write_expr_to_string(gbString str, Ast *node) {
break;
}
- str = write_expr_to_string(str, ce->proc);
+ str = write_expr_to_string(str, ce->proc, shorthand);
str = gb_string_appendc(str, "(");
for_array(i, ce->args) {
@@ -10524,7 +10685,7 @@ gbString write_expr_to_string(gbString str, Ast *node) {
if (i > 0) {
str = gb_string_appendc(str, ", ");
}
- str = write_expr_to_string(str, arg);
+ str = write_expr_to_string(str, arg, shorthand);
}
str = gb_string_appendc(str, ")");
case_end;
@@ -10533,17 +10694,36 @@ gbString write_expr_to_string(gbString str, Ast *node) {
str = gb_string_appendc(str, "typeid");
if (tt->specialization) {
str = gb_string_appendc(str, "/");
- str = write_expr_to_string(str, tt->specialization);
+ str = write_expr_to_string(str, tt->specialization, shorthand);
}
case_end;
case_ast_node(pt, ProcType, node);
str = gb_string_appendc(str, "proc(");
- str = write_expr_to_string(str, pt->params);
+ str = write_expr_to_string(str, pt->params, shorthand);
str = gb_string_appendc(str, ")");
if (pt->results != nullptr) {
str = gb_string_appendc(str, " -> ");
- str = write_expr_to_string(str, pt->results);
+
+ bool parens_needed = false;
+ if (pt->results && pt->results->kind == Ast_FieldList) {
+ for_array(i, pt->results->FieldList.list) {
+ Ast *field = pt->results->FieldList.list[i];
+ ast_node(f, Field, field);
+ if (f->names.count != 0) {
+ parens_needed = true;
+ break;
+ }
+ }
+ }
+
+ if (parens_needed) {
+ str = gb_string_append_rune(str, '(');
+ }
+ str = write_expr_to_string(str, pt->results, shorthand);
+ if (parens_needed) {
+ str = gb_string_append_rune(str, ')');
+ }
}
case_end;
@@ -10553,7 +10733,11 @@ gbString write_expr_to_string(gbString str, Ast *node) {
if (st->is_packed) str = gb_string_appendc(str, "#packed ");
if (st->is_raw_union) str = gb_string_appendc(str, "#raw_union ");
str = gb_string_append_rune(str, '{');
- str = write_struct_fields_to_string(str, st->fields);
+ if (shorthand) {
+ str = gb_string_appendc(str, "...");
+ } else {
+ str = write_struct_fields_to_string(str, st->fields);
+ }
str = gb_string_append_rune(str, '}');
case_end;
@@ -10561,30 +10745,38 @@ gbString write_expr_to_string(gbString str, Ast *node) {
case_ast_node(st, UnionType, node);
str = gb_string_appendc(str, "union ");
str = gb_string_append_rune(str, '{');
- str = write_struct_fields_to_string(str, st->variants);
+ if (shorthand) {
+ str = gb_string_appendc(str, "...");
+ } else {
+ str = write_struct_fields_to_string(str, st->variants);
+ }
str = gb_string_append_rune(str, '}');
case_end;
case_ast_node(et, EnumType, node);
str = gb_string_appendc(str, "enum ");
if (et->base_type != nullptr) {
- str = write_expr_to_string(str, et->base_type);
+ str = write_expr_to_string(str, et->base_type, shorthand);
str = gb_string_append_rune(str, ' ');
}
str = gb_string_append_rune(str, '{');
- for_array(i, et->fields) {
- if (i > 0) {
- str = gb_string_appendc(str, ", ");
+ if (shorthand) {
+ str = gb_string_appendc(str, "...");
+ } else {
+ for_array(i, et->fields) {
+ if (i > 0) {
+ str = gb_string_appendc(str, ", ");
+ }
+ str = write_expr_to_string(str, et->fields[i], shorthand);
}
- str = write_expr_to_string(str, et->fields[i]);
}
str = gb_string_append_rune(str, '}');
case_end;
case_ast_node(rt, RelativeType, node);
- str = write_expr_to_string(str, rt->tag);
+ str = write_expr_to_string(str, rt->tag, shorthand);
str = gb_string_appendc(str, "" );
- str = write_expr_to_string(str, rt->type);
+ str = write_expr_to_string(str, rt->type, shorthand);
case_end;
@@ -10594,12 +10786,12 @@ gbString write_expr_to_string(gbString str, Ast *node) {
if (i > 0) {
str = gb_string_appendc(str, ", ");
}
- str = write_expr_to_string(str, ia->param_types[i]);
+ str = write_expr_to_string(str, ia->param_types[i], shorthand);
}
str = gb_string_appendc(str, ")");
if (ia->return_type != nullptr) {
str = gb_string_appendc(str, " -> ");
- str = write_expr_to_string(str, ia->return_type);
+ str = write_expr_to_string(str, ia->return_type, shorthand);
}
if (ia->has_side_effects) {
str = gb_string_appendc(str, " #side_effects");
@@ -10612,9 +10804,13 @@ gbString write_expr_to_string(gbString str, Ast *node) {
str = gb_string_appendc(str, inline_asm_dialect_strings[ia->dialect]);
}
str = gb_string_appendc(str, " {");
- str = write_expr_to_string(str, ia->asm_string);
- str = gb_string_appendc(str, ", ");
- str = write_expr_to_string(str, ia->constraints_string);
+ if (shorthand) {
+ str = gb_string_appendc(str, "...");
+ } else {
+ str = write_expr_to_string(str, ia->asm_string, shorthand);
+ str = gb_string_appendc(str, ", ");
+ str = write_expr_to_string(str, ia->constraints_string, shorthand);
+ }
str = gb_string_appendc(str, "}");
case_end;
}
@@ -10623,5 +10819,8 @@ gbString write_expr_to_string(gbString str, Ast *node) {
}
gbString expr_to_string(Ast *expression) {
- return write_expr_to_string(gb_string_make(heap_allocator(), ""), expression);
+ return write_expr_to_string(gb_string_make(heap_allocator(), ""), expression, false);
+}
+gbString expr_to_string_shorthand(Ast *expression) {
+ return write_expr_to_string(gb_string_make(heap_allocator(), ""), expression, true);
}