Support explicit discards better by allowing multiple declared "_" vars

This commit is contained in:
Bruce Hill 2024-09-18 00:30:05 -04:00
parent fe3d45c37a
commit ec88848f6b
2 changed files with 12 additions and 3 deletions

View File

@ -455,6 +455,9 @@ CORD compile_statement(env_t *env, ast_t *ast)
if (test->expr->tag == Declare) {
auto decl = Match(test->expr, Declare);
const char *varname = Match(decl->var, Var)->name;
if (streq(varname, "_"))
return compile_statement(env, WrapAST(ast, DocTest, .expr=decl->value, .output=test->output, .skip_source=test->skip_source));
CORD var = CORD_all("$", Match(decl->var, Var)->name);
type_t *t = get_type(env, decl->value);
CORD val_code = compile_maybe_incref(env, decl->value);
@ -560,6 +563,8 @@ CORD compile_statement(env_t *env, ast_t *ast)
auto decl = Match(ast, Declare);
if (decl->value->tag == Use) {
return compile_statement(env, decl->value);
} else if (streq(Match(decl->var, Var)->name, "_")) { // Explicit discard
return CORD_all("(void)", compile(env, decl->value), ";");
} else {
type_t *t = get_type(env, decl->value);
if (t->tag == AbortType || t->tag == VoidType || t->tag == ReturnType)

View File

@ -260,6 +260,8 @@ void bind_statement(env_t *env, ast_t *statement)
case Declare: {
auto decl = Match(statement, Declare);
const char *name = Match(decl->var, Var)->name;
if (streq(name, "_")) // Explicit discard
return;
if (get_binding(env, name))
code_err(decl->var, "A %T called '%s' has already been defined", get_binding(env, name)->type, name);
if (decl->value->tag == Use) {
@ -1164,10 +1166,12 @@ type_t *get_type(env_t *env, ast_t *ast)
falsey_scope = fresh_scope(env);
bind_statement(falsey_scope, if_->condition);
truthy_scope = fresh_scope(env);
const char *varname = Match(Match(if_->condition, Declare)->var, Var)->name;
set_binding(truthy_scope, varname,
new(binding_t, .type=Match(condition_type, OptionalType)->type));
if (!streq(varname, "_")) {
truthy_scope = fresh_scope(env);
set_binding(truthy_scope, varname,
new(binding_t, .type=Match(condition_type, OptionalType)->type));
}
} else if (if_->condition->tag == Var) {
type_t *condition_type = get_type(env, if_->condition);
if (condition_type->tag == OptionalType) {