From cb962cc19004c08381b4425da8cf12a36456a7cb Mon Sep 17 00:00:00 2001 From: Thomas Voss Date: Sat, 29 Jun 2024 13:14:26 +0200 Subject: Add (x & y) and (x | y) --- src/analyzer.c | 33 ++++++++++++++++++--------------- src/codegen.c | 4 ++++ src/parser.c | 12 ++++-------- src/parser.h | 10 +++++++++- 4 files changed, 35 insertions(+), 24 deletions(-) (limited to 'src') 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, -- cgit v1.2.3