diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-02-22 13:09:46 -0500 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-02-22 13:09:46 -0500 |
| commit | bfdb2da9e12775a0caa8de35f1d114181918529a (patch) | |
| tree | 4c371610df56b3730fac57591e10bc4ff2f48b25 | |
| parent | 663182abdf0cb34c1b4331bfe29cefe14e053f73 (diff) | |
Implement power (^)
| -rw-r--r-- | compile.c | 74 | ||||
| -rw-r--r-- | nextlang.h | 1 | ||||
| -rw-r--r-- | typecheck.c | 6 |
3 files changed, 44 insertions, 37 deletions
@@ -179,139 +179,139 @@ CORD compile(env_t *env, ast_t *ast) CORD lhs = compile(env, binop->lhs); CORD rhs = compile(env, binop->rhs); - type_t *lhs_t = get_type(env, binop->lhs); - type_t *rhs_t = get_type(env, binop->rhs); - type_t *operand_t; - if (can_promote(rhs_t, lhs_t)) - operand_t = lhs_t; - else if (can_promote(lhs_t, rhs_t)) - operand_t = rhs_t; - else - code_err(ast, "I can't do binary operations between %T and %T", lhs_t, rhs_t); + type_t *result_t = get_type(env, ast); switch (binop->op) { + case BINOP_POWER: { + if (result_t->tag != NumType) + code_err(ast, "Exponentiation is only supported for Num types"); + if (Match(result_t, NumType)->bits == 32) + return CORD_all("powf(", lhs, ", ", rhs, ")"); + else + return CORD_all("pow(", lhs, ", ", rhs, ")"); + } case BINOP_MULT: { - if (operand_t->tag != IntType && operand_t->tag != NumType) + if (result_t->tag != IntType && result_t->tag != NumType) code_err(ast, "Math operations are only supported for numeric types"); return CORD_asprintf("(%r * %r)", lhs, rhs); } case BINOP_DIVIDE: { - if (operand_t->tag != IntType && operand_t->tag != NumType) + if (result_t->tag != IntType && result_t->tag != NumType) code_err(ast, "Math operations are only supported for numeric types"); return CORD_asprintf("(%r / %r)", lhs, rhs); } case BINOP_MOD: { - if (operand_t->tag != IntType && operand_t->tag != NumType) + if (result_t->tag != IntType && result_t->tag != NumType) code_err(ast, "Math operations are only supported for numeric types"); return CORD_asprintf("mod(%r, %r)", lhs, rhs); } case BINOP_MOD1: { - if (operand_t->tag != IntType && operand_t->tag != NumType) + if (result_t->tag != IntType && result_t->tag != NumType) code_err(ast, "Math operations are only supported for numeric types"); return CORD_asprintf("mod1(%r, %r)", lhs, rhs); } case BINOP_PLUS: { - if (operand_t->tag != IntType && operand_t->tag != NumType) + if (result_t->tag != IntType && result_t->tag != NumType) code_err(ast, "Math operations are only supported for numeric types"); return CORD_asprintf("(%r + %r)", lhs, rhs); } case BINOP_MINUS: { - if (operand_t->tag != IntType && operand_t->tag != NumType) + if (result_t->tag != IntType && result_t->tag != NumType) code_err(ast, "Math operations are only supported for numeric types"); return CORD_asprintf("(%r - %r)", lhs, rhs); } case BINOP_LSHIFT: { - if (operand_t->tag != IntType && operand_t->tag != NumType) + if (result_t->tag != IntType && result_t->tag != NumType) code_err(ast, "Math operations are only supported for numeric types"); return CORD_asprintf("(%r << %r)", lhs, rhs); } case BINOP_RSHIFT: { - if (operand_t->tag != IntType && operand_t->tag != NumType) + if (result_t->tag != IntType && result_t->tag != NumType) code_err(ast, "Math operations are only supported for numeric types"); return CORD_asprintf("(%r >> %r)", lhs, rhs); } case BINOP_EQ: { - switch (operand_t->tag) { + switch (result_t->tag) { case BoolType: case IntType: case NumType: case PointerType: case FunctionType: return CORD_asprintf("(%r == %r)", lhs, rhs); default: - return CORD_asprintf("generic_equal($stack(%r), $stack(%r), %r)", lhs, rhs, compile_type_info(env, operand_t)); + return CORD_asprintf("generic_equal($stack(%r), $stack(%r), %r)", lhs, rhs, compile_type_info(env, result_t)); } } case BINOP_NE: { - switch (operand_t->tag) { + switch (result_t->tag) { case BoolType: case IntType: case NumType: case PointerType: case FunctionType: return CORD_asprintf("(%r != %r)", lhs, rhs); default: - return CORD_asprintf("!generic_equal($stack(%r), $stack(%r), %r)", lhs, rhs, compile_type_info(env, operand_t)); + return CORD_asprintf("!generic_equal($stack(%r), $stack(%r), %r)", lhs, rhs, compile_type_info(env, result_t)); } } case BINOP_LT: { - switch (operand_t->tag) { + switch (result_t->tag) { case BoolType: case IntType: case NumType: case PointerType: case FunctionType: return CORD_asprintf("(%r < %r)", lhs, rhs); default: - return CORD_asprintf("(generic_compare($stack(%r), $stack(%r), %r) < 0)", lhs, rhs, compile_type_info(env, operand_t)); + return CORD_asprintf("(generic_compare($stack(%r), $stack(%r), %r) < 0)", lhs, rhs, compile_type_info(env, result_t)); } } case BINOP_LE: { - switch (operand_t->tag) { + switch (result_t->tag) { case BoolType: case IntType: case NumType: case PointerType: case FunctionType: return CORD_asprintf("(%r <= %r)", lhs, rhs); default: - return CORD_asprintf("(generic_compare($stack(%r), $stack(%r), %r) <= 0)", lhs, rhs, compile_type_info(env, operand_t)); + return CORD_asprintf("(generic_compare($stack(%r), $stack(%r), %r) <= 0)", lhs, rhs, compile_type_info(env, result_t)); } } case BINOP_GT: { - switch (operand_t->tag) { + switch (result_t->tag) { case BoolType: case IntType: case NumType: case PointerType: case FunctionType: return CORD_asprintf("(%r > %r)", lhs, rhs); default: - return CORD_asprintf("(generic_compare($stack(%r), $stack(%r), %r) > 0)", lhs, rhs, compile_type_info(env, operand_t)); + return CORD_asprintf("(generic_compare($stack(%r), $stack(%r), %r) > 0)", lhs, rhs, compile_type_info(env, result_t)); } } case BINOP_GE: { - switch (operand_t->tag) { + switch (result_t->tag) { case BoolType: case IntType: case NumType: case PointerType: case FunctionType: return CORD_asprintf("(%r >= %r)", lhs, rhs); default: - return CORD_asprintf("(generic_compare($stack(%r), $stack(%r), %r) >= 0)", lhs, rhs, compile_type_info(env, operand_t)); + return CORD_asprintf("(generic_compare($stack(%r), $stack(%r), %r) >= 0)", lhs, rhs, compile_type_info(env, result_t)); } } case BINOP_AND: { - if (operand_t->tag == BoolType) + if (result_t->tag == BoolType) return CORD_asprintf("(%r && %r)", lhs, rhs); - else if (operand_t->tag == IntType) + else if (result_t->tag == IntType) return CORD_asprintf("(%r & %r)", lhs, rhs); else code_err(ast, "Boolean operators are only supported for Bool and integer types"); } case BINOP_OR: { - if (operand_t->tag == BoolType) + if (result_t->tag == BoolType) return CORD_asprintf("(%r || %r)", lhs, rhs); - else if (operand_t->tag == IntType) + else if (result_t->tag == IntType) return CORD_asprintf("(%r | %r)", lhs, rhs); else code_err(ast, "Boolean operators are only supported for Bool and integer types"); } case BINOP_XOR: { - if (operand_t->tag == BoolType || operand_t->tag == IntType) + if (result_t->tag == BoolType || result_t->tag == IntType) return CORD_asprintf("(%r ^ %r)", lhs, rhs); else code_err(ast, "Boolean operators are only supported for Bool and integer types"); } case BINOP_CONCAT: { - switch (operand_t->tag) { + switch (result_t->tag) { case StringType: { return CORD_all("CORD_cat(", lhs, ", ", rhs, ")"); } case ArrayType: { return CORD_all("({ array_t $joined = ", lhs, ", $rhs = ", rhs, ";\n" - "Array__insert_all(&$joined, $rhs, 0, ", compile_type_info(env, operand_t), ");\n" + "Array__insert_all(&$joined, $rhs, 0, ", compile_type_info(env, result_t), ");\n" "$joined; })"); } default: - code_err(ast, "Concatenation isn't supported for %T types", operand_t); + code_err(ast, "Concatenation isn't supported for %T types", result_t); } } default: break; @@ -3,6 +3,7 @@ #include <err.h> #include <gc.h> #include <gc/cord.h> +#include <math.h> #include <signal.h> #include <stdbool.h> #include <stdint.h> diff --git a/typecheck.c b/typecheck.c index ad1062d1..30ac197d 100644 --- a/typecheck.c +++ b/typecheck.c @@ -457,6 +457,12 @@ type_t *get_type(env_t *env, ast_t *ast) code_err(ast, "I can't compare these two different types: %T vs %T", lhs_t, rhs_t); return Type(BoolType); } + case BINOP_POWER: { + type_t *result = get_math_type(env, ast, lhs_t, rhs_t); + if (result->tag == NumType) + return result; + return Type(NumType, .bits=64); + } default: { return get_math_type(env, ast, lhs_t, rhs_t); } |
