aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Voss <mail@thomasvoss.com> 2024-06-29 13:14:26 +0200
committerThomas Voss <mail@thomasvoss.com> 2024-06-29 13:14:26 +0200
commitcb962cc19004c08381b4425da8cf12a36456a7cb (patch)
tree377162577c7153fcf81e139a4c1b726d0f6410fe
parent8dbb8162f99efe0f35b99df6379c71336a575222 (diff)
Add (x & y) and (x | y)
-rw-r--r--src/analyzer.c33
-rw-r--r--src/codegen.c4
-rw-r--r--src/parser.c12
-rw-r--r--src/parser.h10
4 files changed, 35 insertions, 24 deletions
diff --git a/src/analyzer.c b/src/analyzer.c
index ad69c69..4f5500a 100644
--- a/src/analyzer.c
+++ b/src/analyzer.c
@@ -330,9 +330,11 @@ analyzeexpr(struct azctx ctx, scope_t *scps, type_t *types, ast_t ast,
return ni;
}
case ASTBINADD:
+ case ASTBINAND:
case ASTBINDIV:
case ASTBINMOD:
case ASTBINMUL:
+ case ASTBINIOR:
case ASTBINSHL:
case ASTBINSHR:
case ASTBINSUB:
@@ -344,24 +346,19 @@ analyzeexpr(struct azctx ctx, scope_t *scps, type_t *types, ast_t ast,
idx_t ni = analyzeexpr(ctx, scps, types, ast, aux, toks, rhs);
bool isshift = ast.kinds[i] == ASTBINSHL || ast.kinds[i] == ASTBINSHR;
-
if (!isshift && !typecompat(types[lhs], types[rhs]))
err("analyzer: Binary oprand type mismatch");
- if (ast.kinds[i] == ASTBINMOD) {
- if (types[lhs].kind != TYPE_NUM || types[lhs].isfloat)
- err("analyzer: Remainder is not defined for non-integer types");
- if (types[rhs].kind != TYPE_NUM || types[rhs].isfloat)
- err("analyzer: Remainder is not defined for non-integer types");
- } else if (ast.kinds[i] == ASTBINXOR) {
- if (types[lhs].kind != TYPE_NUM || types[lhs].isfloat)
- err("analyzer: XOR is not defined for non-integer types");
- } else if (isshift) {
- if (types[lhs].kind != TYPE_NUM || types[lhs].isfloat
- || types[rhs].kind != TYPE_NUM || types[rhs].isfloat)
- {
- err("analyzer: Bit shift is not defined for non-integer types");
- }
+ static const bool int_only[UINT8_MAX + 1] = {
+ [ASTBINAND] = true, [ASTBINIOR] = true, [ASTBINMOD] = true,
+ [ASTBINSHL] = true, [ASTBINSHR] = true, [ASTBINXOR] = true,
+ };
+
+ if (int_only[ast.kinds[i]]
+ && (types[lhs].kind != TYPE_NUM || types[lhs].isfloat
+ || types[rhs].kind != TYPE_NUM || types[rhs].isfloat))
+ {
+ err("analyzer: Operation not defined for non-integer types");
}
/* In the expression ‘x ⋆ y’ where ⋆ is a binary operator, the
@@ -614,11 +611,15 @@ out:
}
break;
}
+ case ASTBINAND:
+ case ASTBINIOR:
case ASTBINMOD:
case ASTBINXOR: {
static void (*const mpz_fns[UINT8_MAX + 1])(mpz_t, const mpz_t,
const mpz_t) = {
['%'] = mpz_tdiv_q,
+ ['&'] = mpz_and,
+ ['|'] = mpz_ior,
['~'] = mpz_xor,
};
@@ -630,6 +631,8 @@ out:
ni = constfoldexpr(ctx, folds, scps, types, ast, toks, types[i], rhs);
if (MPQ_IS_INIT(folds[lhs]) && MPQ_IS_INIT(folds[rhs])) {
+ assert(MPQ_IS_WHOLE(folds[lhs]));
+ assert(MPQ_IS_WHOLE(folds[rhs]));
mpq_init(folds[i]);
mpz_fns[ast.kinds[i]](mpq_numref(folds[i]), mpq_numref(folds[lhs]),
mpq_numref(folds[rhs]));
diff --git a/src/codegen.c b/src/codegen.c
index ff16b73..a744f31 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -216,7 +216,9 @@ codegentypedexpr(struct cgctx ctx, idx_t i, type_t type, LLVMValueRef *outv)
return ni;
}
case ASTBINADD:
+ case ASTBINAND:
case ASTBINDIV:
+ case ASTBINIOR:
case ASTBINMOD:
case ASTBINMUL:
case ASTBINSHL:
@@ -230,7 +232,9 @@ codegentypedexpr(struct cgctx ctx, idx_t i, type_t type, LLVMValueRef *outv)
const char *name;
} binoptbl[UINT8_MAX + 1] = {
['+'] = {{LLVMBuildAdd, LLVMBuildAdd}, "add"},
+ ['&'] = {{LLVMBuildAnd, LLVMBuildAnd}, "and"},
['*'] = {{LLVMBuildMul, LLVMBuildMul}, "mul"},
+ ['|'] = {{LLVMBuildOr, LLVMBuildOr}, "ior"},
['-'] = {{LLVMBuildSub, LLVMBuildSub}, "sub"},
['/'] = {{LLVMBuildUDiv, LLVMBuildSDiv}, "div"},
['%'] = {{LLVMBuildURem, LLVMBuildSRem}, "rem"},
diff --git a/src/parser.c b/src/parser.c
index 45961b0..ea8f00e 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -67,9 +67,11 @@ fwdnode(ast_t ast, idx_t i)
i = ast.kids[i].rhs;
break;
case ASTBINADD:
+ case ASTBINAND:
case ASTBINDIV:
case ASTBINMOD:
case ASTBINMUL:
+ case ASTBINIOR:
case ASTBINSHL:
case ASTBINSHR:
case ASTBINSUB:
@@ -281,14 +283,8 @@ idx_t
parseexprinc(ast_t *ast, lexemes_t toks, idx_t lhs, int minprec)
{
static const int prectbl[UINT8_MAX + 1] = {
- ['+'] = 1,
- ['-'] = 1,
- ['~'] = 1,
- ['%'] = 2,
- ['*'] = 2,
- ['/'] = 2,
- [LEXLANGL_DBL] = 2,
- [LEXRANGL_DBL] = 2,
+ ['+'] = 1, ['-'] = 1, ['|'] = 1, ['~'] = 1, ['%'] = 2,
+ ['&'] = 2, ['*'] = 2, ['/'] = 2, [LEXLANGL_DBL] = 2, [LEXRANGL_DBL] = 2,
};
uint8_t op = toks.kinds[toksidx];
diff --git a/src/parser.h b/src/parser.h
index fdb1a79..32acc96 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -81,10 +81,18 @@ enum {
‘lhs % rhs’ */
ASTBINMOD = '%',
- /* Binary xor
+ /* Binary XOR
‘lhs ~ rhs’ */
ASTBINXOR = '~',
+ /* Binary bitwise AND
+ ‘lhs & rhs’ */
+ ASTBINAND = '&',
+
+ /* Binary bitwise OR
+ ‘lhs & rhs’ */
+ ASTBINIOR = '|',
+
/* Binary left shift
‘lhs << rhs’ */
ASTBINSHL = UINT8_MAX - 2,