diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-05-09 16:21:31 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-05-09 16:21:31 +0100 |
| commit | c6d531df9597253ee95593c56e61039fe4e40ba2 (patch) | |
| tree | 8469ee00657577f4909891e8773231351f54b3cd /src | |
| parent | 8677c81da7ca8af37c49a203a18fd7beab74f023 (diff) | |
Add %% operator (divisor modulo)
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_expr.c | 4 | ||||
| -rw-r--r-- | src/exact_value.c | 1 | ||||
| -rw-r--r-- | src/ir.c | 10 | ||||
| -rw-r--r-- | src/parser.c | 2 | ||||
| -rw-r--r-- | src/tokenizer.c | 5 |
5 files changed, 21 insertions, 1 deletions
diff --git a/src/check_expr.c b/src/check_expr.c index 089f706e4..4dcb04c07 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -1864,8 +1864,10 @@ bool check_binary_op(Checker *c, Operand *o, Token op) { break; case Token_Mod: + case Token_ModMod: case Token_AndNot: case Token_ModEq: + case Token_ModModEq: case Token_AndNotEq: if (!is_type_integer(type)) { error(op, "Operator `%.*s` is only allowed with integers", LIT(op.string)); @@ -2669,8 +2671,10 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { switch (op.kind) { case Token_Quo: case Token_Mod: + case Token_ModMod: case Token_QuoEq: case Token_ModEq: + case Token_ModModEq: if ((x->mode == Addressing_Constant || is_type_integer(x->type)) && y->mode == Addressing_Constant) { bool fail = false; diff --git a/src/exact_value.c b/src/exact_value.c index eec5d157a..b6e30ef83 100644 --- a/src/exact_value.c +++ b/src/exact_value.c @@ -595,6 +595,7 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y) case Token_Quo: return exact_value_float(fmod(cast(f64)a, cast(f64)b)); case Token_QuoEq: c = a / b; break; // NOTE(bill): Integer division case Token_Mod: c = a % b; break; + case Token_ModMod: c = ((a % b) + b)%b; break; case Token_And: c = a & b; break; case Token_Or: c = a | b; break; case Token_Xor: c = a ^ b; break; @@ -2073,6 +2073,7 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue * case Token_Mul: case Token_Quo: case Token_Mod: + case Token_ModMod: case Token_And: case Token_Or: case Token_Xor: @@ -2081,6 +2082,14 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue * break; } + if (op == Token_ModMod) { + irValue *n = left; + irValue *m = right; + irValue *a = ir_emit(proc, ir_instr_binary_op(proc, Token_Mod, n, m, type)); + irValue *b = ir_emit(proc, ir_instr_binary_op(proc, Token_Add, a, m, type)); + return ir_emit(proc, ir_instr_binary_op(proc, Token_Mod, b, m, type)); + } + return ir_emit(proc, ir_instr_binary_op(proc, op, left, right, type)); } @@ -3744,6 +3753,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { case Token_Mul: case Token_Quo: case Token_Mod: + case Token_ModMod: case Token_And: case Token_Or: case Token_Xor: diff --git a/src/parser.c b/src/parser.c index 7054adfa0..fb8d5d91b 100644 --- a/src/parser.c +++ b/src/parser.c @@ -2136,6 +2136,7 @@ i32 token_precedence(AstFile *f, TokenKind t) { case Token_Mul: case Token_Quo: case Token_Mod: + case Token_ModMod: case Token_And: case Token_AndNot: case Token_Shl: @@ -2305,6 +2306,7 @@ AstNode *parse_simple_stmt(AstFile *f, bool in_stmt_ok) { case Token_MulEq: case Token_QuoEq: case Token_ModEq: + case Token_ModModEq: case Token_AndEq: case Token_OrEq: case Token_XorEq: diff --git a/src/tokenizer.c b/src/tokenizer.c index bc979a784..08496a6d1 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -25,6 +25,7 @@ TOKEN_KIND(Token__OperatorBegin, "_OperatorBegin"), \ TOKEN_KIND(Token_Mul, "*"), \ TOKEN_KIND(Token_Quo, "/"), \ TOKEN_KIND(Token_Mod, "%"), \ + TOKEN_KIND(Token_ModMod, "%%"), \ TOKEN_KIND(Token_And, "&"), \ TOKEN_KIND(Token_Or, "|"), \ TOKEN_KIND(Token_Xor, "~"), \ @@ -41,6 +42,7 @@ TOKEN_KIND(Token__AssignOpBegin, "_AssignOpBegin"), \ TOKEN_KIND(Token_MulEq, "*="), \ TOKEN_KIND(Token_QuoEq, "/="), \ TOKEN_KIND(Token_ModEq, "%="), \ + TOKEN_KIND(Token_ModModEq, "%%="), \ TOKEN_KIND(Token_AndEq, "&="), \ TOKEN_KIND(Token_OrEq, "|="), \ TOKEN_KIND(Token_XorEq, "~="), \ @@ -892,8 +894,9 @@ Token tokenizer_get_token(Tokenizer *t) { case '}': token.kind = Token_CloseBrace; break; case '\\': token.kind = Token_BackSlash; break; + case '%': token.kind = token_kind_dub_eq(t, '%', Token_Mod, Token_ModEq, Token_ModMod, Token_ModModEq); break; + case '*': token.kind = token_kind_variant2(t, Token_Mul, Token_MulEq); break; - case '%': token.kind = token_kind_variant2(t, Token_Mod, Token_ModEq); break; case '=': token.kind = token_kind_variant2(t, Token_Eq, Token_CmpEq); break; case '~': token.kind = token_kind_variant2(t, Token_Xor, Token_XorEq); break; case '!': token.kind = token_kind_variant2(t, Token_Not, Token_NotEq); break; |