From 553f3df5df05d11cc4c6a1f2cceb18b18452704d Mon Sep 17 00:00:00 2001
From: "Wolfgang (Blub) Bumiller" <blub@speed.at>
Date: Fri, 23 Nov 2012 14:24:58 +0100
Subject: [PATCH] *= and /= operators

---
 parser.c             | 44 ++++++++++++++++++++++++++++++++++++++++++++
 tests/operators.qc   | 18 +++++++++++++++---
 tests/operators.tmpl |  4 ++++
 3 files changed, 63 insertions(+), 3 deletions(-)

diff --git a/parser.c b/parser.c
index 6e150c1..c8d1c11 100644
--- a/parser.c
+++ b/parser.c
@@ -971,6 +971,50 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
                     return false;
             };
             break;
+        case opid2('*','='):
+        case opid2('/','='):
+            if (exprs[1]->expression.vtype != TYPE_FLOAT ||
+                !(exprs[0]->expression.vtype == TYPE_FLOAT ||
+                  exprs[0]->expression.vtype == TYPE_VECTOR))
+            {
+                ast_type_to_string(exprs[0], ty1, sizeof(ty1));
+                ast_type_to_string(exprs[1], ty2, sizeof(ty2));
+                parseerror(parser, "invalid types used in expression: %s and %s",
+                           ty1, ty2);
+                return false;
+            }
+            if (ast_istype(exprs[0], ast_entfield))
+                assignop = type_storep_instr[exprs[0]->expression.vtype];
+            else
+                assignop = type_store_instr[exprs[0]->expression.vtype];
+            switch (exprs[0]->expression.vtype) {
+                case TYPE_FLOAT:
+                    out = (ast_expression*)ast_binstore_new(ctx, assignop,
+                                                            (op->id == opid2('*','=') ? INSTR_MUL_F : INSTR_DIV_F),
+                                                            exprs[0], exprs[1]);
+                    break;
+                case TYPE_VECTOR:
+                    if (op->id == opid2('*','=')) {
+                        out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_MUL_VF,
+                                                                exprs[0], exprs[1]);
+                    } else {
+                        /* there's no DIV_VF */
+                        out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F,
+                                                              (ast_expression*)parser_const_float_1(parser),
+                                                              exprs[1]);
+                        if (!out)
+                            return false;
+                        out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_MUL_VF,
+                                                                exprs[0], out);
+                    }
+                    break;
+                default:
+                    parseerror(parser, "invalid types used in expression: cannot add or subtract type %s and %s",
+                               type_name[exprs[0]->expression.vtype],
+                               type_name[exprs[1]->expression.vtype]);
+                    return false;
+            };
+            break;
     }
 #undef NotSameType
 
diff --git a/tests/operators.qc b/tests/operators.qc
index 1c23e7a..e440ec5 100644
--- a/tests/operators.qc
+++ b/tests/operators.qc
@@ -1,6 +1,7 @@
-void   print(...)   = #1;
-string ftos (float) = #2;
-entity() spawn = #3;
+void   print(...)    = #1;
+string ftos (float)  = #2;
+string vtos (vector) = #5;
+entity spawn()       = #3;
 
 .float mem;
 
@@ -39,4 +40,15 @@ void main() {
 	// postfix on members
 	print(ftos(e.mem--), " = ");
 	print(ftos(e.mem+1), "\n");
+
+	// compounds in general
+	a = 3;
+	print(ftos(a *= 2), " = 6\n");
+	print(ftos(a /= 2), " = 3\n");
+
+    // compounds on vectors
+	vector v;
+	v = '3 4 5';
+	print(vtos(v *= 2), " = '6 8 10'\n");
+	print(vtos(v /= 2), " = '3 4 5'\n");
 }
diff --git a/tests/operators.tmpl b/tests/operators.tmpl
index 1e12706..06426ac 100644
--- a/tests/operators.tmpl
+++ b/tests/operators.tmpl
@@ -12,3 +12,7 @@ M: 11 = 11
 M: 4
 M: 2
 M: 12 = 12
+M: 6 = 6
+M: 3 = 3
+M: '6 8 10' = '6 8 10'
+M: '3 4 5' = '3 4 5'
-- 
2.39.5