From 005bf43ed23f10785f9df8bc5f9eede0ccc2e2d6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net>
Date: Sat, 29 Sep 2001 01:47:04 -0700
Subject: [PATCH] some fixes for arr[*]+=integer;

Rev: src/docode.c:1.135
Rev: src/interpret_functions.h:1.96
Rev: src/testsuite.in:1.455
Rev: src/treeopt.in:1.66
---
 src/docode.c              | 183 +++++++++++++++++++++++++++++---------
 src/interpret_functions.h |  18 ++--
 src/testsuite.in          |  95 +++++++++++++++++++-
 src/treeopt.in            |   8 +-
 4 files changed, 251 insertions(+), 53 deletions(-)

diff --git a/src/docode.c b/src/docode.c
index 840b7b041d..0953ae9f12 100644
--- a/src/docode.c
+++ b/src/docode.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: docode.c,v 1.134 2001/09/29 06:19:26 hubbe Exp $");
+RCSID("$Id: docode.c,v 1.135 2001/09/29 08:47:03 hubbe Exp $");
 #include "las.h"
 #include "program.h"
 #include "pike_types.h"
@@ -521,6 +521,27 @@ static int do_encode_automap_arg_list(node *n,
   }
 }
 
+static void emit_builtin_svalue(char *func)
+{
+  INT32 tmp1;
+  struct pike_string *n1=make_shared_string(func);
+  node *n=find_module_identifier(n1,0);
+  free_string(n1);
+
+  switch(n?n->token:0)
+  {
+    case F_CONSTANT:
+      tmp1=store_constant(&n->u.sval,
+			  n->tree_info & OPT_EXTERNAL_DEPEND,
+			  n->name);
+      emit1(F_CONSTANT, DO_NOT_WARN((INT32)tmp1));
+      break;
+
+    default:
+      my_yyerror("docode: Failed to make svalue for builtin %s",func);
+  }
+  free_node(n);
+}
 
 static int do_docode2(node *n, INT16 flags)
 {
@@ -718,22 +739,11 @@ static int do_docode2(node *n, INT16 flags)
   case F_MULT_EQ:
   case F_MOD_EQ:
   case F_DIV_EQ:
-    tmp1=do_docode(CAR(n),DO_LVALUE);
-#ifdef PIKE_DEBUG
-    if(tmp1 != 2)
-      fatal("HELP! FATAL INTERNAL COMPILER ERROR (7)\n");
-#endif
-    
-
     if(CAR(n)->token == F_AUTO_MAP_MARKER ||
        CDR(n)->token == F_AUTO_MAP_MARKER)
     {
       char *opname;
-      struct pike_string *opstr;
-      node *op;
 
-      emit0(F_MARK);
-      
       if(CAR(n)->token == F_AUTO_MAP_MARKER)
       {
 	int depth=0;
@@ -743,11 +753,14 @@ static int do_docode2(node *n, INT16 flags)
 	  depth++;
 	  tmp=CAR(tmp);
 	}
+	tmp1=do_docode(tmp,DO_LVALUE);
+	emit0(F_MARK);
 	emit0(F_MARK);
 	emit0(F_LTOSVAL);
 	emit1(F_NUMBER,depth);
 	emit_apply_builtin("__builtin.automap_marker");
       }else{
+	tmp1=do_docode(CAR(n),DO_LVALUE);
 	emit0(F_LTOSVAL);
       }
 
@@ -768,17 +781,8 @@ static int do_docode2(node *n, INT16 flags)
 	  opname="`make gcc happy";
       }
 
-      opstr=findstring(opname);
-      if(!opstr || !(op=find_module_identifier(opstr, 0)))
-      {
-	my_yyerror("Failed to find operator %s\n",opname);
-	do_pop(2);
-	return 1;
-      }
-      
-      code_expression(op, 0, "assignment");
-      free_node(op);
-      emit0(F_SWAP);
+      emit_builtin_svalue(opname);
+      emit2(F_REARRANGE,1,1);
 
       if(CDR(n)->token == F_AUTO_MAP)
       {
@@ -788,6 +792,12 @@ static int do_docode2(node *n, INT16 flags)
       }
       emit_apply_builtin("__automap__");
     }else{
+      tmp1=do_docode(CAR(n),DO_LVALUE);
+#ifdef PIKE_DEBUG
+      if(tmp1 != 2)
+	fatal("HELP! FATAL INTERNAL COMPILER ERROR (7)\n");
+#endif
+
       if(n->token == F_ADD_EQ && (flags & DO_POP))
       {
 	code_expression(CDR(n), 0, "assignment");
@@ -987,35 +997,125 @@ static int do_docode2(node *n, INT16 flags)
 
   case F_INC:
   case F_POST_INC:
-    tmp1=do_docode(CAR(n),DO_LVALUE);
+    if(CAR(n)->token == F_AUTO_MAP_MARKER)
+    {
+      int depth=0;
+      int ret=0;
+      node *tmp=CAR(n);
+      while(tmp->token == F_AUTO_MAP_MARKER)
+      {
+	depth++;
+	tmp=CAR(tmp);
+      }
+
+      tmp1=do_docode(tmp,DO_LVALUE);
+      if(n->token == F_POST_INC)
+      {
+	emit0(F_LTOSVAL);
+	emit2(F_REARRANGE,1,2);
+	ret++;
+	flags|=DO_POP;
+      }
+
 #ifdef PIKE_DEBUG
-    if(tmp1 != 2)
-      fatal("HELP! FATAL INTERNAL COMPILER ERROR (1)\n");
+      if(tmp1 != 2)
+	fatal("HELP! FATAL INTERNAL COMPILER ERROR (1)\n");
 #endif
 
-    if(flags & DO_POP)
-    {
-      emit0(F_INC_AND_POP);
-      return 0;
+      emit0(F_MARK);
+      emit0(F_MARK);
+      emit0(F_LTOSVAL);
+      emit1(F_NUMBER, depth);
+      emit_apply_builtin("__builtin.automap_marker");
+      emit_builtin_svalue("`+");
+      emit2(F_REARRANGE,1,1);
+      emit1(F_NUMBER, 1);
+      emit_apply_builtin("__automap__");
+
+      if(flags & DO_POP)
+      {
+	emit0(F_ASSIGN_AND_POP);
+      }else{
+	emit0(F_ASSIGN);
+	ret++;
+      }
+      return ret;
     }else{
-      emit0(n->token);
-      return 1;
+      tmp1=do_docode(CAR(n),DO_LVALUE);
+#ifdef PIKE_DEBUG
+      if(tmp1 != 2)
+	fatal("HELP! FATAL INTERNAL COMPILER ERROR (1)\n");
+#endif
+
+      if(flags & DO_POP)
+      {
+	emit0(F_INC_AND_POP);
+	return 0;
+      }else{
+	emit0(n->token);
+	return 1;
+      }
     }
 
   case F_DEC:
   case F_POST_DEC:
-    tmp1=do_docode(CAR(n),DO_LVALUE);
+    if(CAR(n)->token == F_AUTO_MAP_MARKER)
+    {
+      int depth=0;
+      int ret=0;
+      node *tmp=CAR(n);
+      while(tmp->token == F_AUTO_MAP_MARKER)
+      {
+	depth++;
+	tmp=CAR(tmp);
+      }
+
+      tmp1=do_docode(tmp,DO_LVALUE);
+      if(n->token == F_POST_DEC)
+      {
+	emit0(F_LTOSVAL);
+	emit2(F_REARRANGE,1,2);
+	ret++;
+	flags|=DO_POP;
+      }
+
 #ifdef PIKE_DEBUG
-    if(tmp1 != 2)
-      fatal("HELP! FATAL INTERNAL COMPILER ERROR (2)\n");
+      if(tmp1 != 2)
+	fatal("HELP! FATAL INTERNAL COMPILER ERROR (1)\n");
 #endif
-    if(flags & DO_POP)
-    {
-      emit0(F_DEC_AND_POP);
-      return 0;
+
+      emit0(F_MARK);
+      emit0(F_MARK);
+      emit0(F_LTOSVAL);
+      emit1(F_NUMBER, depth);
+      emit_apply_builtin("__builtin.automap_marker");
+      emit_builtin_svalue("`-");
+      emit2(F_REARRANGE,1,1);
+      emit1(F_NUMBER, 1);
+      emit_apply_builtin("__automap__");
+
+      if(flags & DO_POP)
+      {
+	emit0(F_ASSIGN_AND_POP);
+      }else{
+	emit0(F_ASSIGN);
+	ret++;
+      }
+      return ret;
     }else{
-      emit0(n->token);
-      return 1;
+      tmp1=do_docode(CAR(n),DO_LVALUE);
+#ifdef PIKE_DEBUG
+      if(tmp1 != 2)
+	fatal("HELP! FATAL INTERNAL COMPILER ERROR (2)\n");
+#endif
+      if(flags & DO_POP)
+      {
+	emit0(F_DEC_AND_POP);
+	return 0;
+      }else{
+	emit0(n->token);
+	return 1;
+      }
     }
 
   case F_FOR:
@@ -2056,7 +2156,6 @@ static int do_docode2(node *n, INT16 flags)
     return 1;
 
   case F_AUTO_MAP_MARKER:
-    if(flags & DO_LVALUE) return do_docode(CAR(n), flags);
     yyerror("[*] not supported here.\n");
     emit0(F_CONST0);
     return 1;
diff --git a/src/interpret_functions.h b/src/interpret_functions.h
index 3ac1ad6904..1e28ae25b0 100644
--- a/src/interpret_functions.h
+++ b/src/interpret_functions.h
@@ -1,5 +1,5 @@
 /*
- * $Id: interpret_functions.h,v 1.95 2001/09/29 06:19:27 hubbe Exp $
+ * $Id: interpret_functions.h,v 1.96 2001/09/29 08:47:03 hubbe Exp $
  *
  * Opcode definitions for the interpreter.
  */
@@ -198,11 +198,16 @@ OPCODE1(F_CONSTANT, "constant", {
   print_return_value();
 });
 
-OPCODE0(F_SWAP,"swap",{
-  struct svalue tmp;
-  tmp=Pike_sp[-2];
-  Pike_sp[-2]=Pike_sp[-1];
-  Pike_sp[-1]=tmp;
+
+/* Generic swap instruction:
+ * swaps the arg1 top values with the arg2 values beneath
+ */
+OPCODE2(F_REARRANGE,"rearrange",{
+  int e;
+  check_stack(arg2);
+  MEMCPY(Pike_sp,Pike_sp-arg1-arg2,sizeof(struct svalue)*arg2);
+  MEMMOVE(Pike_sp-arg1-arg2,Pike_sp-arg1,sizeof(struct svalue)*arg1);
+  MEMCPY(Pike_sp-arg2,Pike_sp,sizeof(struct svalue)*arg2);
 });
 
 /* The rest of the basic 'push value' instructions */	
@@ -583,6 +588,7 @@ OPCODE0(F_LTOSVAL, "lvalue to svalue", {
   dmalloc_touch_svalue(Pike_sp-1);
   lvalue_to_svalue_no_free(Pike_sp, Pike_sp-2);
   Pike_sp++;
+  print_return_value();
 });
 
 OPCODE0(F_LTOSVAL2, "ltosval2", {
diff --git a/src/testsuite.in b/src/testsuite.in
index e681582994..d2e27e0d08 100644
--- a/src/testsuite.in
+++ b/src/testsuite.in
@@ -1,4 +1,4 @@
-test_true([["$Id: testsuite.in,v 1.454 2001/09/28 00:01:45 hubbe Exp $"]]);
+test_true([["$Id: testsuite.in,v 1.455 2001/09/29 08:47:03 hubbe Exp $"]]);
 
 cond([[all_constants()->_verify_internals]],
 [[
@@ -1750,11 +1750,15 @@ dnl test_compile_error([[void foo() { return destruct(this_object()); }]])
 test_any([[class foo { constant x=17; }; class bar { inherit foo; constant x=18; }; return bar()->x;]],18)
 test_program([[inline string foo(string s){ while(s[0] == ' ' || s[0] == '\t') s = s[1..]; return(s); } string a() { return foo("   bar"); }]])
 
+
+// lambda function tests
+
 test_true([[lambda(int x) { return lambda() { return x; };}]])
 test_eq([[lambda(int x) { return lambda() { return x; };}(4)()]],4)
 test_eq([[lambda(int x) { return lambda() { return x; };}(17)()]],17)
 test_eq([[lambda(int x) { return lambda() { return lambda() { return x; };};}(17)()()]],17)
 
+// local function tests
 test_eq(120,
         [[ lambda()
            {
@@ -1771,6 +1775,32 @@ test_eq([[function f;
 	  { {int _i = i; f = lambda(int j) { return _i+j; }; } int FEL; }
 	return f(17);]]);
 
+test_any([[
+  int x,y,z;
+  function p;
+  void foo() { y+=7; };
+  void bar()
+  {
+    foo();
+    void gazonk()
+    {
+      foo();
+      void quux()
+      {
+        foo();
+        y+=4711;
+      };
+      p=quux;
+    };
+
+    gazonk();
+    gazonk();
+  };
+  foo();
+  bar();
+  p();
+  return y;
+]], 7 * 5 + 4711 )
 
 test_any([[
    int x=1;
@@ -1779,6 +1809,7 @@ test_any([[
    return x;
 ]], 11)
 
+// implicit lambda tests
 test_any([[
    int x=1;
    void for10(function f) { for(int e=0;e<10;e++) f(); };
@@ -1997,9 +2028,71 @@ test_any_equal([[
 ]],
 [[ ({ ({15,25}), ({35,45}) }) ]])
 
+test_any_equal([[
+  mixed a=({1,2,3});
+  a[*] += -2;
+  return a;
+]], [[ ({-1,0,1}) ]])
+
+test_any_equal([[
+  mixed a=({1,2,3});
+  a[*] += -1;
+  return a;
+]], [[ ({0,1,2}) ]])
+
+test_any_equal([[
+  mixed a=({1,2,3});
+  a[*] += 0;
+  return a;
+]], [[ ({1,2,3}) ]])
+
+test_any_equal([[
+  mixed a=({1,2,3});
+  a[*] += 1;
+  return a;
+]], [[ ({2,3,4}) ]])
+
+test_any_equal([[
+  mixed a=({1,2,3});
+  a[*] += 2;
+  return a;
+]], [[ ({3,4,5}) ]])
+
+
+test_any_equal([[
+  mixed a=({1,2,3});
+  return a[*] += -2;
+]], [[ ({-1,0,1}) ]])
+
+test_any_equal([[
+  mixed a=({1,2,3});
+  return a[*] += -1;
+]], [[ ({0,1,2}) ]])
+
+test_any_equal([[
+  mixed a=({1,2,3});
+  return a[*] += 0;
+]], [[ ({1,2,3}) ]])
+
+test_any_equal([[
+  mixed a=({1,2,3});
+  return a[*] += 1;
+]], [[ ({2,3,4}) ]])
+
+test_any_equal([[
+  mixed a=({1,2,3});
+  return a[*] += 2;
+]], [[ ({3,4,5}) ]])
+
 test_equal([[ "foo"[ ({ 2,0,1,2 })[*] ]  ]],
            [[ ({ 'o', 'f', 'o', 'o' }) ]])
 
+test_equal([[ ({ ({1}), ({2}), ({3}) })[*][0] ]],
+           [[ ({ 1,2,3 }) ]])
+
+test_equal([[ ({ ({1,2}), ({3,4}), ({5,6}) })[*][ ({0,1,1})[*] ] ]],
+           [[ ({ 1,4,6 }) ]])
+
 // map tests
 test_any_equal(array a = ({({1,0,0}),({1,1,0}),({0,1,1})}); return map(a,`[],1);,
                ({0,1,1}))
diff --git a/src/treeopt.in b/src/treeopt.in
index 98bd6df357..b7cc0c3196 100644
--- a/src/treeopt.in
+++ b/src/treeopt.in
@@ -1,6 +1,6 @@
 // -*- c -*-
 //
-// $Id: treeopt.in,v 1.65 2001/09/07 03:15:07 hubbe Exp $
+// $Id: treeopt.in,v 1.66 2001/09/29 08:47:04 hubbe Exp $
 //
 // The tree optimizer
 //
@@ -733,7 +733,7 @@ F_NOT(F_NE(0, 1), *):
 
 
 // a += 0  ->  a
-F_ADD_EQ(0, 1 = F_CONSTANT[$$->u.sval.type == T_INT]
+F_ADD_EQ(0 [ $$->token != F_AUTO_MAP_MARKER ], 1 = F_CONSTANT[$$->u.sval.type == T_INT]
 	 [!($$->u.sval.u.integer)]):
   $0;
 
@@ -748,8 +748,8 @@ F_ADD_EQ(0, 1 = F_CONSTANT[$$->u.sval.type == T_INT]
   F_DEC($0, -);
 
 
-// a += 0  ->  a
-F_SUB_EQ(0, 1 = F_CONSTANT[$$->u.sval.type == T_INT]
+// a -= 0  ->  a
+F_SUB_EQ(0 [ $$->token != F_AUTO_MAP_MARKER ], 1 = F_CONSTANT[$$->u.sval.type == T_INT]
 	 [!($$->u.sval.u.integer)]):
   $0;
 
-- 
GitLab