diff options
| author | Thomas Voss <mail@thomasvoss.com> | 2024-06-29 13:14:26 +0200 | 
|---|---|---|
| committer | Thomas Voss <mail@thomasvoss.com> | 2024-06-29 13:14:26 +0200 | 
| commit | cb962cc19004c08381b4425da8cf12a36456a7cb (patch) | |
| tree | 377162577c7153fcf81e139a4c1b726d0f6410fe /src/analyzer.c | |
| parent | 8dbb8162f99efe0f35b99df6379c71336a575222 (diff) | |
Add (x & y) and (x | y)
Diffstat (limited to 'src/analyzer.c')
| -rw-r--r-- | src/analyzer.c | 33 | 
1 files changed, 18 insertions, 15 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]));  |