aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compile/comparisons.c95
-rw-r--r--src/compile/comparisons.h8
-rw-r--r--src/compile/expressions.c81
3 files changed, 107 insertions, 77 deletions
diff --git a/src/compile/comparisons.c b/src/compile/comparisons.c
new file mode 100644
index 00000000..851088d8
--- /dev/null
+++ b/src/compile/comparisons.c
@@ -0,0 +1,95 @@
+// This file defines how to compile comparisons
+
+#include "../ast.h"
+#include "../config.h"
+#include "../environment.h"
+#include "../stdlib/text.h"
+#include "../typecheck.h"
+#include "promotions.h"
+#include "types.h"
+
+Text_t compile_comparison(env_t *env, ast_t *ast) {
+
+ switch (ast->tag) {
+ case Equals:
+ case NotEquals: {
+ binary_operands_t binop = BINARY_OPERANDS(ast);
+
+ type_t *lhs_t = get_type(env, binop.lhs);
+ type_t *rhs_t = get_type(env, binop.rhs);
+ type_t *operand_t;
+ if (binop.lhs->tag == Int && is_numeric_type(rhs_t)) {
+ operand_t = rhs_t;
+ } else if (binop.rhs->tag == Int && is_numeric_type(lhs_t)) {
+ operand_t = lhs_t;
+ } else if (can_compile_to_type(env, binop.rhs, lhs_t)) {
+ operand_t = lhs_t;
+ } else if (can_compile_to_type(env, binop.lhs, rhs_t)) {
+ operand_t = rhs_t;
+ } else {
+ code_err(ast, "I can't do comparisons between ", type_to_str(lhs_t), " and ", type_to_str(rhs_t));
+ }
+
+ Text_t lhs, rhs;
+ lhs = compile_to_type(env, binop.lhs, operand_t);
+ rhs = compile_to_type(env, binop.rhs, operand_t);
+
+ switch (operand_t->tag) {
+ case BigIntType:
+ return Texts(ast->tag == Equals ? EMPTY_TEXT : Text("!"), "Int$equal_value(", lhs, ", ", rhs, ")");
+ case BoolType:
+ case ByteType:
+ case IntType:
+ case NumType:
+ case PointerType:
+ case FunctionType: return Texts("(", lhs, ast->tag == Equals ? " == " : " != ", rhs, ")");
+ default:
+ return Texts(ast->tag == Equals ? EMPTY_TEXT : Text("!"), "generic_equal(stack(", lhs, "), stack(", rhs,
+ "), ", compile_type_info(operand_t), ")");
+ }
+ }
+ case LessThan:
+ case LessThanOrEquals:
+ case GreaterThan:
+ case GreaterThanOrEquals:
+ case Compare: {
+ binary_operands_t cmp = BINARY_OPERANDS(ast);
+
+ type_t *lhs_t = get_type(env, cmp.lhs);
+ type_t *rhs_t = get_type(env, cmp.rhs);
+ type_t *operand_t;
+ if (cmp.lhs->tag == Int && is_numeric_type(rhs_t)) {
+ operand_t = rhs_t;
+ } else if (cmp.rhs->tag == Int && is_numeric_type(lhs_t)) {
+ operand_t = lhs_t;
+ } else if (can_compile_to_type(env, cmp.rhs, lhs_t)) {
+ operand_t = lhs_t;
+ } else if (can_compile_to_type(env, cmp.lhs, rhs_t)) {
+ operand_t = rhs_t;
+ } else {
+ code_err(ast, "I can't do comparisons between ", type_to_str(lhs_t), " and ", type_to_str(rhs_t));
+ }
+
+ Text_t lhs = compile_to_type(env, cmp.lhs, operand_t);
+ Text_t rhs = compile_to_type(env, cmp.rhs, operand_t);
+
+ if (ast->tag == Compare)
+ return Texts("generic_compare(stack(", lhs, "), stack(", rhs, "), ", compile_type_info(operand_t), ")");
+
+ const char *op = binop_operator(ast->tag);
+ switch (operand_t->tag) {
+ case BigIntType: return Texts("(Int$compare_value(", lhs, ", ", rhs, ") ", op, " 0)");
+ case BoolType:
+ case ByteType:
+ case IntType:
+ case NumType:
+ case PointerType:
+ case FunctionType: return Texts("(", lhs, " ", op, " ", rhs, ")");
+ default:
+ return Texts("(generic_compare(stack(", lhs, "), stack(", rhs, "), ", compile_type_info(operand_t), ") ",
+ op, " 0)");
+ }
+ }
+ default: code_err(ast, "This is not a comparison!");
+ }
+}
diff --git a/src/compile/comparisons.h b/src/compile/comparisons.h
new file mode 100644
index 00000000..105387d5
--- /dev/null
+++ b/src/compile/comparisons.h
@@ -0,0 +1,8 @@
+// This file defines how to compile comparisons
+#pragma once
+
+#include "../ast.h"
+#include "../environment.h"
+#include "../stdlib/datatypes.h"
+
+Text_t compile_comparison(env_t *env, ast_t *ast);
diff --git a/src/compile/expressions.c b/src/compile/expressions.c
index 404beff2..7c9779e6 100644
--- a/src/compile/expressions.c
+++ b/src/compile/expressions.c
@@ -10,6 +10,7 @@
#include "../typecheck.h"
#include "binops.h"
#include "blocks.h"
+#include "comparisons.h"
#include "conditionals.h"
#include "declarations.h"
#include "enums.h"
@@ -150,88 +151,14 @@ Text_t compile(env_t *env, ast_t *ast) {
case UnsignedRightShift:
case And:
case Or:
- case Xor: {
- return compile_binary_op(env, ast);
- }
+ case Xor: return compile_binary_op(env, ast);
case Equals:
- case NotEquals: {
- binary_operands_t binop = BINARY_OPERANDS(ast);
-
- type_t *lhs_t = get_type(env, binop.lhs);
- type_t *rhs_t = get_type(env, binop.rhs);
- type_t *operand_t;
- if (binop.lhs->tag == Int && is_numeric_type(rhs_t)) {
- operand_t = rhs_t;
- } else if (binop.rhs->tag == Int && is_numeric_type(lhs_t)) {
- operand_t = lhs_t;
- } else if (can_compile_to_type(env, binop.rhs, lhs_t)) {
- operand_t = lhs_t;
- } else if (can_compile_to_type(env, binop.lhs, rhs_t)) {
- operand_t = rhs_t;
- } else {
- code_err(ast, "I can't do comparisons between ", type_to_str(lhs_t), " and ", type_to_str(rhs_t));
- }
-
- Text_t lhs, rhs;
- lhs = compile_to_type(env, binop.lhs, operand_t);
- rhs = compile_to_type(env, binop.rhs, operand_t);
-
- switch (operand_t->tag) {
- case BigIntType:
- return Texts(ast->tag == Equals ? EMPTY_TEXT : Text("!"), "Int$equal_value(", lhs, ", ", rhs, ")");
- case BoolType:
- case ByteType:
- case IntType:
- case NumType:
- case PointerType:
- case FunctionType: return Texts("(", lhs, ast->tag == Equals ? " == " : " != ", rhs, ")");
- default:
- return Texts(ast->tag == Equals ? EMPTY_TEXT : Text("!"), "generic_equal(stack(", lhs, "), stack(", rhs,
- "), ", compile_type_info(operand_t), ")");
- }
- }
+ case NotEquals:
case LessThan:
case LessThanOrEquals:
case GreaterThan:
case GreaterThanOrEquals:
- case Compare: {
- binary_operands_t cmp = BINARY_OPERANDS(ast);
-
- type_t *lhs_t = get_type(env, cmp.lhs);
- type_t *rhs_t = get_type(env, cmp.rhs);
- type_t *operand_t;
- if (cmp.lhs->tag == Int && is_numeric_type(rhs_t)) {
- operand_t = rhs_t;
- } else if (cmp.rhs->tag == Int && is_numeric_type(lhs_t)) {
- operand_t = lhs_t;
- } else if (can_compile_to_type(env, cmp.rhs, lhs_t)) {
- operand_t = lhs_t;
- } else if (can_compile_to_type(env, cmp.lhs, rhs_t)) {
- operand_t = rhs_t;
- } else {
- code_err(ast, "I can't do comparisons between ", type_to_str(lhs_t), " and ", type_to_str(rhs_t));
- }
-
- Text_t lhs = compile_to_type(env, cmp.lhs, operand_t);
- Text_t rhs = compile_to_type(env, cmp.rhs, operand_t);
-
- if (ast->tag == Compare)
- return Texts("generic_compare(stack(", lhs, "), stack(", rhs, "), ", compile_type_info(operand_t), ")");
-
- const char *op = binop_operator(ast->tag);
- switch (operand_t->tag) {
- case BigIntType: return Texts("(Int$compare_value(", lhs, ", ", rhs, ") ", op, " 0)");
- case BoolType:
- case ByteType:
- case IntType:
- case NumType:
- case PointerType:
- case FunctionType: return Texts("(", lhs, " ", op, " ", rhs, ")");
- default:
- return Texts("(generic_compare(stack(", lhs, "), stack(", rhs, "), ", compile_type_info(operand_t), ") ",
- op, " 0)");
- }
- }
+ case Compare: return compile_comparison(env, ast);
case TextLiteral:
case TextJoin: return compile_text_ast(env, ast);
case Path: {