Support logical binary operators on optionals (promote to booleans)
This commit is contained in:
parent
478ddad9aa
commit
325b367a13
10
compile.c
10
compile.c
@ -70,6 +70,12 @@ static bool promote(env_t *env, ast_t *ast, CORD *code, type_t *actual, type_t *
|
||||
return true;
|
||||
}
|
||||
|
||||
// Optional -> Bool promotion
|
||||
if (actual->tag == OptionalType && needed->tag == BoolType) {
|
||||
*code = CORD_all("(!", check_none(actual, *code), ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Automatic optional checking for nums:
|
||||
if (needed->tag == NumType && actual->tag == OptionalType && Match(actual, OptionalType)->type->tag == NumType) {
|
||||
*code = CORD_all("({ ", compile_declaration(actual, "opt"), " = ", *code, "; ",
|
||||
@ -2155,6 +2161,8 @@ CORD compile(env_t *env, ast_t *ast)
|
||||
return CORD_all("({ ", compile_declaration(lhs_t, "lhs"), " = ", compile(env, binop->lhs), "; ",
|
||||
check_none(lhs_t, "lhs"), " ? ", compile(env, binop->rhs), " : ",
|
||||
optional_into_nonnone(lhs_t, "lhs"), "; })");
|
||||
} else if (rhs_t->tag == BoolType) {
|
||||
return CORD_all("((!", check_none(lhs_t, compile(env, binop->lhs)), ") || ", compile(env, binop->rhs), ")");
|
||||
} else {
|
||||
code_err(ast, "I don't know how to do an 'or' operation between %T and %T", lhs_t, rhs_t);
|
||||
}
|
||||
@ -2166,6 +2174,8 @@ CORD compile(env_t *env, ast_t *ast)
|
||||
} else if (rhs_t->tag == OptionalType && type_eq(lhs_t, rhs_t)) {
|
||||
return CORD_all("({ ", compile_declaration(lhs_t, "lhs"), " = ", compile(env, binop->lhs), "; ",
|
||||
check_none(lhs_t, "lhs"), " ? lhs : ", compile(env, binop->rhs), "; })");
|
||||
} else if (rhs_t->tag == BoolType) {
|
||||
return CORD_all("((!", check_none(lhs_t, compile(env, binop->lhs)), ") && ", compile(env, binop->rhs), ")");
|
||||
} else {
|
||||
code_err(ast, "I don't know how to do an 'or' operation between %T and %T", lhs_t, rhs_t);
|
||||
}
|
||||
|
@ -326,3 +326,8 @@ func main():
|
||||
|
||||
>> [Struct(5,"A")?, Struct(6,"B"), Struct(7,"C")]
|
||||
= [Struct(x=5, y="A"), Struct(x=6, y="B"), Struct(x=7, y="C")]
|
||||
|
||||
if 5? or no:
|
||||
say("Binary op 'or' works with optionals")
|
||||
else:
|
||||
fail("Failed to do binary op 'or' on optional")
|
||||
|
@ -1027,6 +1027,9 @@ type_t *get_type(env_t *env, ast_t *ast)
|
||||
case BINOP_AND: {
|
||||
if (lhs_t->tag == BoolType && rhs_t->tag == BoolType) {
|
||||
return lhs_t;
|
||||
} else if ((lhs_t->tag == BoolType && rhs_t->tag == OptionalType) ||
|
||||
(lhs_t->tag == OptionalType && rhs_t->tag == BoolType)) {
|
||||
return Type(BoolType);
|
||||
} else if (lhs_t->tag == BoolType && (rhs_t->tag == AbortType || rhs_t->tag == ReturnType)) {
|
||||
return lhs_t;
|
||||
} else if (rhs_t->tag == AbortType || rhs_t->tag == ReturnType) {
|
||||
@ -1048,6 +1051,9 @@ type_t *get_type(env_t *env, ast_t *ast)
|
||||
case BINOP_OR: {
|
||||
if (lhs_t->tag == BoolType && rhs_t->tag == BoolType) {
|
||||
return lhs_t;
|
||||
} else if ((lhs_t->tag == BoolType && rhs_t->tag == OptionalType) ||
|
||||
(lhs_t->tag == OptionalType && rhs_t->tag == BoolType)) {
|
||||
return Type(BoolType);
|
||||
} else if (lhs_t->tag == BoolType && (rhs_t->tag == AbortType || rhs_t->tag == ReturnType)) {
|
||||
return lhs_t;
|
||||
} else if ((is_int_type(lhs_t) && is_int_type(rhs_t))
|
||||
@ -1075,6 +1081,9 @@ type_t *get_type(env_t *env, ast_t *ast)
|
||||
case BINOP_XOR: {
|
||||
if (lhs_t->tag == BoolType && rhs_t->tag == BoolType) {
|
||||
return lhs_t;
|
||||
} else if ((lhs_t->tag == BoolType && rhs_t->tag == OptionalType) ||
|
||||
(lhs_t->tag == OptionalType && rhs_t->tag == BoolType)) {
|
||||
return Type(BoolType);
|
||||
} else if ((is_int_type(lhs_t) && is_int_type(rhs_t))
|
||||
|| (lhs_t->tag == ByteType && rhs_t->tag == ByteType)) {
|
||||
return get_math_type(env, ast, lhs_t, rhs_t);
|
||||
|
3
types.c
3
types.c
@ -358,6 +358,9 @@ PUREFUNC bool can_promote(type_t *actual, type_t *needed)
|
||||
return true;
|
||||
|
||||
if (actual->tag == OptionalType) {
|
||||
if (needed->tag == BoolType)
|
||||
return true;
|
||||
|
||||
// Ambiguous `none` to concrete optional
|
||||
if (Match(actual, OptionalType)->type == NULL)
|
||||
return (needed->tag == OptionalType);
|
||||
|
Loading…
Reference in New Issue
Block a user