code / tomo

Lines41.3K C23.7K Markdown9.7K YAML5.0K Tomo2.3K
7 others 763
Python231 Shell230 make212 INI47 Text21 SVG16 Lua6
(110 lines)
1 // This file defines how to compile comparisons
3 #include "../ast.h"
4 #include "../config.h"
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) {
11 switch (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 ">=";
18 default: return NULL;
22 Text_t compile_comparison(env_t *env, ast_t *ast) {
23 switch (ast->tag) {
24 case Equals:
25 case NotEquals: {
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);
30 type_t *operand_t;
31 if (type_eq(lhs_t, rhs_t)) {
32 operand_t = lhs_t;
33 } else if (binop.lhs->tag == Int && is_numeric_type(rhs_t)) {
34 operand_t = rhs_t;
35 } else if (binop.rhs->tag == Int && is_numeric_type(lhs_t)) {
36 operand_t = lhs_t;
37 } else if (can_compile_to_type(with_enum_scope(env, lhs_t), binop.rhs, lhs_t)) {
38 operand_t = lhs_t;
39 } else if (can_compile_to_type(env, binop.lhs, rhs_t)) {
40 operand_t = rhs_t;
41 } else {
42 code_err(ast, "I can't do comparisons between ", type_to_text(lhs_t), " and ", type_to_text(rhs_t));
44 assert(operand_t);
46 Text_t lhs, rhs;
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) {
51 case BigIntType:
52 return Texts(ast->tag == Equals ? EMPTY_TEXT : Text("!"), "Int$equal_value(", lhs, ", ", rhs, ")");
53 case BoolType:
54 case ByteType:
55 case IntType:
56 case NumType:
57 case PointerType:
58 case FunctionType: return Texts("(", lhs, ast->tag == Equals ? " == " : " != ", rhs, ")");
59 default:
60 return Texts(ast->tag == Equals ? EMPTY_TEXT : Text("!"), "generic_equal(stack(", lhs, "), stack(", rhs,
61 "), ", compile_type_info(operand_t), ")");
64 case LessThan:
65 case LessThanOrEquals:
66 case GreaterThan:
67 case GreaterThanOrEquals:
68 case Compare: {
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);
73 type_t *operand_t;
74 if (type_eq(lhs_t, rhs_t)) {
75 operand_t = lhs_t;
76 } else if (cmp.lhs->tag == Int && is_numeric_type(rhs_t)) {
77 operand_t = rhs_t;
78 } else if (cmp.rhs->tag == Int && is_numeric_type(lhs_t)) {
79 operand_t = lhs_t;
80 } else if (can_compile_to_type(env, cmp.rhs, lhs_t)) {
81 operand_t = lhs_t;
82 } else if (can_compile_to_type(env, cmp.lhs, rhs_t)) {
83 operand_t = rhs_t;
84 } else {
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)");
97 case BoolType:
98 case ByteType:
99 case IntType:
100 case NumType:
101 case PointerType:
102 case FunctionType: return Texts("(", lhs, " ", op, " ", rhs, ")");
103 default:
104 return Texts("(generic_compare(stack(", lhs, "), stack(", rhs, "), ", compile_type_info(operand_t), ") ",
105 op, " 0)");
108 default: code_err(ast, "This is not a comparison!");