aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-05-09 16:21:31 +0100
committerGinger Bill <bill@gingerbill.org>2017-05-09 16:21:31 +0100
commitc6d531df9597253ee95593c56e61039fe4e40ba2 (patch)
tree8469ee00657577f4909891e8773231351f54b3cd /src
parent8677c81da7ca8af37c49a203a18fd7beab74f023 (diff)
Add %% operator (divisor modulo)
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.c4
-rw-r--r--src/exact_value.c1
-rw-r--r--src/ir.c10
-rw-r--r--src/parser.c2
-rw-r--r--src/tokenizer.c5
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;
diff --git a/src/ir.c b/src/ir.c
index 4f8e31bae..28b698b0d 100644
--- a/src/ir.c
+++ b/src/ir.c
@@ -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;