1 // This file defines how to compile comparisons
5 #include "../environment.h"
6 #include "../stdlib/text.h"
7 #include "../typecheck.h"
8 #include "compilation.h"
10 static CONSTFUNC const char *comparison_operator(ast_e tag) {
12 case Equals: return "==";
13 case NotEquals: return "!=";
14 case LessThan: return "<";
15 case LessThanOrEquals: return "<=";
16 case GreaterThan: return ">";
17 case GreaterThanOrEquals: return ">=";
22 Text_t compile_comparison(env_t *env, ast_t *ast) {
26 binary_operands_t binop = BINARY_OPERANDS(ast);
28 type_t *lhs_t = get_type(env, binop.lhs);
29 type_t *rhs_t = get_type(with_enum_scope(env, lhs_t), binop.rhs);
31 if (type_eq(lhs_t, rhs_t)) {
33 } else if (binop.lhs->tag == Int && is_numeric_type(rhs_t)) {
35 } else if (binop.rhs->tag == Int && is_numeric_type(lhs_t)) {
37 } else if (can_compile_to_type(with_enum_scope(env, lhs_t), binop.rhs, lhs_t)) {
39 } else if (can_compile_to_type(env, binop.lhs, rhs_t)) {
42 code_err(ast, "I can't do comparisons between ", type_to_text(lhs_t), " and ", type_to_text(rhs_t));
47 lhs = compile_to_type(env, binop.lhs, operand_t);
48 rhs = compile_to_type(env, binop.rhs, operand_t);
50 switch (operand_t->tag) {
52 return Texts(ast->tag == Equals ? EMPTY_TEXT : Text("!"), "Int$equal_value(", lhs, ", ", rhs, ")");
58 case FunctionType: return Texts("(", lhs, ast->tag == Equals ? " == " : " != ", rhs, ")");
60 return Texts(ast->tag == Equals ? EMPTY_TEXT : Text("!"), "generic_equal(stack(", lhs, "), stack(", rhs,
61 "), ", compile_type_info(operand_t), ")");
65 case LessThanOrEquals:
67 case GreaterThanOrEquals:
69 binary_operands_t cmp = BINARY_OPERANDS(ast);
71 type_t *lhs_t = get_type(env, cmp.lhs);
72 type_t *rhs_t = get_type(env, cmp.rhs);
74 if (type_eq(lhs_t, rhs_t)) {
76 } else if (cmp.lhs->tag == Int && is_numeric_type(rhs_t)) {
78 } else if (cmp.rhs->tag == Int && is_numeric_type(lhs_t)) {
80 } else if (can_compile_to_type(env, cmp.rhs, lhs_t)) {
82 } else if (can_compile_to_type(env, cmp.lhs, rhs_t)) {
85 code_err(ast, "I can't do comparisons between ", type_to_text(lhs_t), " and ", type_to_text(rhs_t));
88 Text_t lhs = compile_to_type(env, cmp.lhs, operand_t);
89 Text_t rhs = compile_to_type(env, cmp.rhs, operand_t);
91 if (ast->tag == Compare)
92 return Texts("generic_compare(stack(", lhs, "), stack(", rhs, "), ", compile_type_info(operand_t), ")");
94 const char *op = comparison_operator(ast->tag);
95 switch (operand_t->tag) {
96 case BigIntType: return Texts("(Int$compare_value(", lhs, ", ", rhs, ") ", op, " 0)");
102 case FunctionType: return Texts("(", lhs, " ", op, " ", rhs, ")");
104 return Texts("(generic_compare(stack(", lhs, "), stack(", rhs, "), ", compile_type_info(operand_t), ") ",
108 default: code_err(ast, "This is not a comparison!");