Support if x := blah: ...
This commit is contained in:
parent
23209a0aab
commit
989dc3f442
32
compile.c
32
compile.c
@ -1196,21 +1196,30 @@ CORD compile_statement(env_t *env, ast_t *ast)
|
|||||||
}
|
}
|
||||||
case If: {
|
case If: {
|
||||||
auto if_ = Match(ast, If);
|
auto if_ = Match(ast, If);
|
||||||
type_t *cond_t = get_type(env, if_->condition);
|
ast_t *condition = if_->condition;
|
||||||
|
CORD code = CORD_EMPTY;
|
||||||
|
if (condition->tag == Declare) {
|
||||||
|
env = fresh_scope(env);
|
||||||
|
code = compile_statement(env, condition);
|
||||||
|
bind_statement(env, condition);
|
||||||
|
condition = Match(condition, Declare)->var;
|
||||||
|
}
|
||||||
|
|
||||||
|
type_t *cond_t = get_type(env, condition);
|
||||||
if (cond_t->tag == PointerType) {
|
if (cond_t->tag == PointerType) {
|
||||||
code_err(if_->condition, "This pointer will always be non-null, so it should not be used in a conditional.");
|
code_err(condition, "This pointer will always be non-null, so it should not be used in a conditional.");
|
||||||
} else if (cond_t->tag != BoolType && cond_t->tag != TextType && cond_t->tag != OptionalType) {
|
} else if (cond_t->tag != BoolType && cond_t->tag != TextType && cond_t->tag != OptionalType) {
|
||||||
code_err(if_->condition, "Only boolean values, optional pointers, and text can be used in conditionals (this is a %T)", cond_t);
|
code_err(condition, "Only boolean values, optional pointers, and text can be used in conditionals (this is a %T)", cond_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
env_t *truthy_scope = env;
|
env_t *truthy_scope = env;
|
||||||
CORD condition;
|
CORD condition_code;
|
||||||
if (cond_t->tag == TextType) {
|
if (cond_t->tag == TextType) {
|
||||||
condition = CORD_all("(", compile(env, if_->condition), ").length");
|
condition_code = CORD_all("(", compile(env, condition), ").length");
|
||||||
} else if (cond_t->tag == OptionalType) {
|
} else if (cond_t->tag == OptionalType) {
|
||||||
if (if_->condition->tag == Var) {
|
if (condition->tag == Var) {
|
||||||
truthy_scope = fresh_scope(env);
|
truthy_scope = fresh_scope(env);
|
||||||
const char *varname = Match(if_->condition, Var)->name;
|
const char *varname = Match(condition, Var)->name;
|
||||||
binding_t *b = get_binding(env, varname);
|
binding_t *b = get_binding(env, varname);
|
||||||
binding_t *nonnull_b = new(binding_t);
|
binding_t *nonnull_b = new(binding_t);
|
||||||
*nonnull_b = *b;
|
*nonnull_b = *b;
|
||||||
@ -1218,14 +1227,17 @@ CORD compile_statement(env_t *env, ast_t *ast)
|
|||||||
nonnull_b->code = compile_optional_into_nonnull(env, b);
|
nonnull_b->code = compile_optional_into_nonnull(env, b);
|
||||||
set_binding(truthy_scope, varname, nonnull_b);
|
set_binding(truthy_scope, varname, nonnull_b);
|
||||||
}
|
}
|
||||||
condition = compile_optional_check(env, if_->condition);
|
condition_code = compile_optional_check(env, condition);
|
||||||
} else {
|
} else {
|
||||||
condition = compile(env, if_->condition);
|
condition_code = compile(env, condition);
|
||||||
}
|
}
|
||||||
|
|
||||||
CORD code = CORD_all("if (", condition, ")", compile_statement(truthy_scope, if_->body));
|
code = CORD_all(code, "if (", condition_code, ")", compile_statement(truthy_scope, if_->body));
|
||||||
if (if_->else_body)
|
if (if_->else_body)
|
||||||
code = CORD_all(code, "\nelse ", compile_statement(env, if_->else_body));
|
code = CORD_all(code, "\nelse ", compile_statement(env, if_->else_body));
|
||||||
|
|
||||||
|
if (if_->condition->tag == Declare)
|
||||||
|
code = CORD_all("{\n", code, "}\n");
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
case Block: {
|
case Block: {
|
||||||
|
5
parse.c
5
parse.c
@ -1003,8 +1003,9 @@ PARSER(parse_if) {
|
|||||||
if (!match_word(&pos, "if"))
|
if (!match_word(&pos, "if"))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ast_t *condition = expect(ctx, start, &pos, parse_expr,
|
ast_t *condition = optional(ctx, &pos, parse_declaration);
|
||||||
"I expected to find a condition for this 'if'");
|
if (!condition)
|
||||||
|
condition = expect(ctx, start, &pos, parse_expr, "I expected to find a condition for this 'if'");
|
||||||
|
|
||||||
ast_t *body = expect(ctx, start, &pos, parse_block, "I expected a body for this 'if' statement");
|
ast_t *body = expect(ctx, start, &pos, parse_block, "I expected a body for this 'if' statement");
|
||||||
|
|
||||||
|
@ -121,3 +121,8 @@ func main():
|
|||||||
fail("Truthy: $nope")
|
fail("Truthy: $nope")
|
||||||
else: !! Falsey: $nope
|
else: !! Falsey: $nope
|
||||||
|
|
||||||
|
|
||||||
|
if yep := maybe_int(yes):
|
||||||
|
>> yep
|
||||||
|
= 123 : Int
|
||||||
|
else: fail("Unreachable")
|
||||||
|
Loading…
Reference in New Issue
Block a user