From dffa0194fd40a258b0719704b911bfb88b78562a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net>
Date: Wed, 15 Jan 1997 21:00:48 -0800
Subject: [PATCH] overloading for -> and [] implemented

Rev: src/docode.c:1.7
Rev: src/interpret.c:1.19
Rev: src/language.yacc:1.17
Rev: src/las.c:1.11
Rev: src/lex.c:1.10
Rev: src/object.c:1.8
Rev: src/peep.c:1.4
Rev: src/peep.in:1.2
Rev: src/program.c:1.12
Rev: src/program.h:1.6
---
 src/docode.c      | 27 +++++++++++++++++++++++++--
 src/interpret.c   | 35 +++++++++++++++++++++++++++--------
 src/language.yacc | 46 +++++++++++++++++++++++++++++++---------------
 src/las.c         |  4 +++-
 src/lex.c         | 13 +++++++++++--
 src/object.c      | 35 +++++++++++++++++++++--------------
 src/peep.c        |  2 ++
 src/peep.in       |  2 +-
 src/program.c     |  4 +++-
 src/program.h     |  4 +++-
 10 files changed, 127 insertions(+), 45 deletions(-)

diff --git a/src/docode.c b/src/docode.c
index 20cb71dbce..b9a9016fb4 100644
--- a/src/docode.c
+++ b/src/docode.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: docode.c,v 1.6 1996/12/04 00:27:10 hubbe Exp $");
+RCSID("$Id: docode.c,v 1.7 1997/01/16 05:00:43 hubbe Exp $");
 #include "las.h"
 #include "program.h"
 #include "language.h"
@@ -267,6 +267,7 @@ static int do_docode2(node *n,int flags)
     case F_GLOBAL:
     case F_IDENTIFIER:
     case F_INDEX:
+    case F_ARROW:
     case F_ARG_LIST:
       break;
     }
@@ -926,12 +927,34 @@ static int do_docode2(node *n,int flags)
   case F_LVALUE_LIST:
     return do_docode(CAR(n),DO_LVALUE)+do_docode(CDR(n),DO_LVALUE);
 
+  case F_ARROW:
+    if(CDR(n)->token != F_CONSTANT || CDR(n)->u.sval.type!=T_STRING)
+      fatal("Bugg in F_ARROW, index not string.");
+    if(flags & DO_LVALUE)
+    {
+      /* FIXME!!!! */
+      tmp1=do_docode(CAR(n), 0);
+      emit(F_ARROW_STRING, store_prog_string(CDR(n)->u.sval.u.string));
+      return 2;
+    }else{
+      tmp1=do_docode(CAR(n), DO_NOT_COPY);
+      emit(F_ARROW, store_prog_string(CDR(n)->u.sval.u.string));
+      if(!(flags & DO_NOT_COPY))
+      {
+	while(n && (n->token==F_INDEX || n->token==F_ARROW)) n=CAR(n);
+	if(n->token==F_CONSTANT && !(n->node_info & OPT_EXTERNAL_DEPEND))
+	  emit2(F_COPY_VALUE);
+      }
+    }
+    return tmp1;
+
   case F_INDEX:
     if(flags & DO_LVALUE)
     {
       tmp1=do_docode(CAR(n), 0);
       if(do_docode(CDR(n),0) != 1)
 	fatal("Internal compiler error, please report this (1).");
+      if(CDR(n)->token != F_CONSTANT) emit2(F_CLEAR_STRING_SUBTYPE);
       return 2;
     }else{
       tmp1=do_docode(CAR(n), DO_NOT_COPY);
@@ -940,7 +963,7 @@ static int do_docode2(node *n,int flags)
       emit2(F_INDEX);
       if(!(flags & DO_NOT_COPY))
       {
-	while(n && n->token==F_INDEX) n=CAR(n);
+	while(n && (n->token==F_INDEX || n->token==F_ARROW)) n=CAR(n);
 	if(n->token==F_CONSTANT && !(n->node_info & OPT_EXTERNAL_DEPEND))
 	  emit2(F_COPY_VALUE);
       }
diff --git a/src/interpret.c b/src/interpret.c
index 63268aee30..ef4286a52d 100644
--- a/src/interpret.c
+++ b/src/interpret.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: interpret.c,v 1.18 1996/12/06 08:30:16 per Exp $");
+RCSID("$Id: interpret.c,v 1.19 1997/01/16 05:00:44 hubbe Exp $");
 #include "interpret.h"
 #include "object.h"
 #include "program.h"
@@ -558,6 +558,15 @@ static void eval_instruction(unsigned char *pc)
       CASE(F_STRING);
       copy_shared_string(sp->u.string,fp->context.prog->strings[GET_ARG()]);
       sp->type=T_STRING;
+      sp->subtype=0;
+      sp++;
+      print_return_value();
+      break;
+
+      CASE(F_ARROW_STRING);
+      copy_shared_string(sp->u.string,fp->context.prog->strings[GET_ARG()]);
+      sp->type=T_STRING;
+      sp->subtype=1; /* Magic */
       sp++;
       print_return_value();
       break;
@@ -784,6 +793,10 @@ static void eval_instruction(unsigned char *pc)
       CASE(F_MARK2); *(mark_sp++)=sp;
       CASE(F_MARK); *(mark_sp++)=sp; break;
 
+      CASE(F_CLEAR_STRING_SUBTYPE);
+      if(sp[-1].type==T_STRING) sp[-1].subtype=0;
+      break;
+
       /* Jumps */
       CASE(F_BRANCH);
       DOJUMP();
@@ -1007,6 +1020,7 @@ static void eval_instruction(unsigned char *pc)
       print_return_value();
       goto do_index;
 
+      CASE(F_ARROW);
       CASE(F_STRING_INDEX);
       copy_shared_string(sp->u.string,fp->context.prog->strings[GET_ARG()]);
       sp->type=T_STRING;
@@ -1333,15 +1347,20 @@ void safe_apply_low(struct object *o,int fun,int args)
   JMP_BUF recovery;
 
   sp-=args;
+  free_svalue(& throw_value);
+  throw_value.type=T_INT;
   if(SETJMP(recovery))
   {
-    ONERROR tmp;
-    SET_ONERROR(tmp,exit_on_error,"Error in handle_error in master object!");
-    assign_svalue_no_free(sp++, & throw_value);
-    APPLY_MASTER("handle_error", 1);
-    pop_stack();
-    UNSET_ONERROR(tmp);
-
+    if(throw_value.type == T_ARRAY)
+    {
+      ONERROR tmp;
+      SET_ONERROR(tmp,exit_on_error,"Error in handle_error in master object!");
+      assign_svalue_no_free(sp++, & throw_value);
+      APPLY_MASTER("handle_error", 1);
+      pop_stack();
+      UNSET_ONERROR(tmp);
+    }
+      
     sp->u.integer = 0;
     sp->subtype=NUMBER_NUMBER;
     sp->type = T_INT;
diff --git a/src/language.yacc b/src/language.yacc
index 3a07e4aa64..5be58913c2 100644
--- a/src/language.yacc
+++ b/src/language.yacc
@@ -22,7 +22,7 @@
 %token F_INC_LOOP F_DEC_LOOP
 %token F_INC_NEQ_LOOP F_DEC_NEQ_LOOP
 
-%token F_INDEX F_INDIRECT F_STRING_INDEX F_LOCAL_INDEX
+%token F_INDEX F_ARROW F_INDIRECT F_STRING_INDEX F_LOCAL_INDEX
 %token F_POS_INT_INDEX F_NEG_INT_INDEX
 %token F_LTOSVAL F_LTOSVAL2
 %token F_PUSH_ARRAY 
@@ -33,8 +33,8 @@
  */
 %token F_LFUN F_GLOBAL F_LOCAL
 %token F_GLOBAL_LVALUE F_LOCAL_LVALUE
-%token F_CLEAR_LOCAL
-%token F_CONSTANT F_FLOAT F_STRING
+%token F_CLEAR_LOCAL F_CLEAR_STRING_SUBTYPE
+%token F_CONSTANT F_FLOAT F_STRING F_ARROW_STRING
 %token F_NUMBER F_NEG_NUMBER F_CONST_1 F_CONST0 F_CONST1 F_BIGNUM
 /*
  * These are the predefined functions that can be accessed from Pike.
@@ -74,7 +74,6 @@
 %token F_APPLY
 %token F_ARG_LIST
 %token F_ARRAY_ID
-%token F_ARROW
 %token F_BREAK
 %token F_CASE
 %token F_CLASS
@@ -156,7 +155,7 @@
 /* This is the grammar definition of Pike. */
 
 #include "global.h"
-RCSID("$Id: language.yacc,v 1.16 1996/12/11 00:48:38 neotron Exp $");
+RCSID("$Id: language.yacc,v 1.17 1997/01/16 05:00:44 hubbe Exp $");
 #ifdef HAVE_MEMORY_H
 #include <memory.h>
 #endif
@@ -1143,7 +1142,7 @@ expr4: string
     { $$=mkefuncallnode("aggregate_multiset",$2); }
   | expr4 F_ARROW F_IDENTIFIER
   {
-    $$=mknode(F_INDEX,$1,mkstrnode($3));
+    $$=mknode(F_ARROW,$1,mkstrnode($3));
     free_string($3);
   }
   ;
@@ -1158,10 +1157,27 @@ idents: F_IDENTIFIER
     }else if((i=isidentifier($1))>=0){
       $$=mkidentifiernode(i);
     }else if((f=lookup_efun($1))){
-	 $$=mkconstantsvaluenode(&f->function);
+      $$=mkconstantsvaluenode(&f->function);
     }else{
-	 my_yyerror("'%s' undefined.",$1->str);
-      $$=0;
+	$$=0;
+      if( get_master() )
+      {
+	reference_shared_string($1);
+	push_string($1);
+	reference_shared_string(current_file);
+	push_string(current_file);
+	SAFE_APPLY_MASTER("resolv", 2);
+	
+	if(throw_value.type == T_STRING)
+	{
+	  my_yyerror("%s",throw_value.u.string->str);
+	}else{
+	  $$=mkconstantsvaluenode(sp-1);
+	  pop_stack();
+	}
+      }else{
+	my_yyerror("'%s' undefined.", $1->str);
+      }
     }
     free_string($1);
   }
@@ -1171,10 +1187,10 @@ idents: F_IDENTIFIER
     f=lookup_efun($3);
     if(!f)
     {
-	 my_yyerror("Unknown efun: %s.",$3->str);
-	 $$=mkintnode(0);
+      my_yyerror("Unknown efun: %s.",$3->str);
+      $$=mkintnode(0);
     }else{
-	 $$=mksvaluenode(&f->function);
+      $$=mksvaluenode(&f->function);
     }
     free_string($3);
   }
@@ -1188,10 +1204,10 @@ idents: F_IDENTIFIER
     idp=fake_program.identifier_references+f;
     if (f<0 || ID_FROM_PTR(&fake_program,idp)->func.offset == -1)
     {
-	 my_yyerror("Undefined identifier %s::%s", $1->str,$3->str);
-	 $$=mkintnode(0);
+      my_yyerror("Undefined identifier %s::%s", $1->str,$3->str);
+      $$=mkintnode(0);
     } else {
-	 $$=mkidentifiernode(f);
+      $$=mkidentifiernode(f);
     }
 
     free_string($1);
diff --git a/src/las.c b/src/las.c
index d68ecec038..d49cf595cb 100644
--- a/src/las.c
+++ b/src/las.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: las.c,v 1.10 1996/12/05 00:47:14 hubbe Exp $");
+RCSID("$Id: las.c,v 1.11 1997/01/16 05:00:45 hubbe Exp $");
 
 #include "language.h"
 #include "interpret.h"
@@ -916,6 +916,7 @@ static void find_written_vars(node *n,
     break;
 
   case F_INDEX:
+  case F_ARROW:
     find_written_vars(CAR(n), p, lvalue);
     find_written_vars(CDR(n), p, 0);
     break;
@@ -1072,6 +1073,7 @@ void fix_type_field(node *n)
     break;
 
   case F_INDEX:
+  case F_ARROW:
     type_a=CAR(n)->type;
     type_b=CDR(n)->type;
     if(!check_indexing(type_a, type_b))
diff --git a/src/lex.c b/src/lex.c
index 7f26c52d6c..ede5f8cca9 100644
--- a/src/lex.c
+++ b/src/lex.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: lex.c,v 1.9 1996/12/06 04:26:57 hubbe Exp $");
+RCSID("$Id: lex.c,v 1.10 1997/01/16 05:00:46 hubbe Exp $");
 #include "language.h"
 #include "array.h"
 #include "lex.h"
@@ -1587,7 +1587,6 @@ static int do_lex2(int literal, YYSTYPE *yylval)
       switch(GETC())
       {
       case '+': tmp="`+"; break;
-      case '-': tmp="`-"; break;
       case '/': tmp="`/"; break;
       case '%': tmp="`%"; break;
       case '*': tmp="`*"; break;
@@ -1595,6 +1594,16 @@ static int do_lex2(int literal, YYSTYPE *yylval)
       case '|': tmp="`|"; break;
       case '^': tmp="`^"; break;
       case '~': tmp="`~"; break;
+      case '-':
+	if(GOBBLE('>'))
+	{
+	  tmp="`->";
+	  if(GOBBLE('=')) tmp="`->=";
+	}else{
+	  tmp="`-";
+	}
+	break;
+
       case '[':
 	if(GOBBLE(']'))
 	{
diff --git a/src/object.c b/src/object.c
index 913d259aae..51e299fedd 100644
--- a/src/object.c
+++ b/src/object.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: object.c,v 1.7 1996/12/05 01:29:45 hubbe Exp $");
+RCSID("$Id: object.c,v 1.8 1997/01/16 05:00:46 hubbe Exp $");
 #include "object.h"
 #include "dynamic_buffer.h"
 #include "interpret.h"
@@ -349,7 +349,7 @@ void low_object_index_no_free(struct svalue *to,
   }
 }
 
-void object_index_no_free(struct svalue *to,
+void object_index_no_free2(struct svalue *to,
 			  struct object *o,
 			  struct svalue *index)
 {
@@ -376,27 +376,30 @@ void object_index_no_free(struct svalue *to,
   }
 }
 
+#define ARROW_INDEX_P(X) ((X)->type==T_STRING && (X)->subtype)
 
-void object_index_no_free2(struct svalue *to,
+void object_index_no_free(struct svalue *to,
 			   struct object *o,
 			   struct svalue *index)
 {
   struct program *p;
+  int lfun;
 
   if(!o || !(p=o->prog))
   {
     error("Lookup in destructed object.\n");
     return; /* make gcc happy */
   }
+  lfun=ARROW_INDEX_P(index) ? LFUN_ARROW : LFUN_INDEX;
 
-  if(p->lfuns[LFUN_INDEX] != -1)
+  if(p->lfuns[lfun] != -1)
   {
     push_svalue(index);
-    apply_lfun(o,LFUN_INDEX,1);
+    apply_lfun(o,lfun,1);
     to=sp;
     sp--;
   } else {
-    object_index_no_free(to,o,index);
+    object_index_no_free2(to,o,index);
   }
 }
 
@@ -435,7 +438,7 @@ static void object_low_set_index(struct object *o,
   }
 }
 
-void object_set_index(struct object *o,
+void object_set_index2(struct object *o,
 		      struct svalue *index,
 		      struct svalue *from)
 {
@@ -460,11 +463,12 @@ void object_set_index(struct object *o,
   }
 }
 
-void object_set_index2(struct object *o,
+void object_set_index(struct object *o,
 		       struct svalue *index,
 		       struct svalue *from)
 {
   struct program *p;
+  int lfun;
 
   if(!o || !(p=o->prog))
   {
@@ -472,14 +476,16 @@ void object_set_index2(struct object *o,
     return; /* make gcc happy */
   }
 
-  if(p->lfuns[LFUN_ASSIGN_INDEX] != -1)
+  lfun=ARROW_INDEX_P(index) ? LFUN_ASSIGN_ARROW : LFUN_ASSIGN_INDEX;
+
+  if(p->lfuns[lfun] != -1)
   {
     push_svalue(index);
     push_svalue(from);
-    apply_lfun(o,LFUN_ASSIGN_INDEX,2);
+    apply_lfun(o,lfun,2);
     pop_stack();
   } else {
-    object_set_index(o,index,from);
+    object_set_index2(o,index,from);
   }
 }
 
@@ -530,12 +536,13 @@ union anything *object_get_item_ptr(struct object *o,
     return 0; /* make gcc happy */
   }
 
+  f=ARROW_INDEX_P(index) ? LFUN_ASSIGN_ARROW : LFUN_ASSIGN_INDEX;
+  if(p->lfuns[f] != -1)
+    error("Cannot do incremental operations on overloaded index (yet).\n");
+
   if(index->type != T_STRING)
     error("Lookup on non-string value.\n");
 
-  if(p->lfuns[LFUN_ASSIGN_INDEX] != -1)
-    error("Cannot do incremental operations on overloaded index (yet).\n");
-
   f=find_shared_string_identifier(index->u.string, p);
   if(f < 0)
   {
diff --git a/src/peep.c b/src/peep.c
index d68d59cda0..cf262eb450 100644
--- a/src/peep.c
+++ b/src/peep.c
@@ -54,6 +54,8 @@ static int hasarg(int opcode)
 
   case F_LFUN:
   case F_STRING:
+  case F_ARROW:
+  case F_ARROW_STRING:
   case F_STRING_INDEX:
   case F_LOCAL_INDEX:
   case F_POS_INT_INDEX:
diff --git a/src/peep.in b/src/peep.in
index 6358766217..1663a3fba3 100644
--- a/src/peep.in
+++ b/src/peep.in
@@ -98,12 +98,12 @@ LE NOT: GT
 GE NOT: LT
 
 LOCAL SIZEOF: SIZEOF_LOCAL ($1a)
-
 STRING INDEX: STRING_INDEX ($1a)
 LOCAL INDEX: LOCAL_INDEX ($1a)
 CONST0 INDEX: POS_INT_INDEX (0)
 CONST_1 INDEX: NEG_INT_INDEX (1)
 CONST1 INDEX: POS_INT_INDEX (1)
+
 NUMBER [$1a < 0] INDEX: NEG_INT_INDEX (-$1a)
 NUMBER [$1a >= 0] INDEX: POS_INT_INDEX ($1a)
 NEG_NUMBER [$1a >= 0] INDEX: NEG_INT_INDEX ($1a)
diff --git a/src/program.c b/src/program.c
index 5d58844d27..0a70679f0d 100644
--- a/src/program.c
+++ b/src/program.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: program.c,v 1.11 1996/12/05 00:47:18 hubbe Exp $");
+RCSID("$Id: program.c,v 1.12 1997/01/16 05:00:48 hubbe Exp $");
 #include "program.h"
 #include "object.h"
 #include "dynamic_buffer.h"
@@ -64,6 +64,8 @@ char *lfun_names[] = {
   "`!",
   "`[]",
   "`[]=",
+  "`->",
+  "`->=",
 };
 
 struct program *first_program = 0;
diff --git a/src/program.h b/src/program.h
index 590861e5a8..93f8f869f0 100644
--- a/src/program.h
+++ b/src/program.h
@@ -33,8 +33,10 @@
 #define LFUN_NOT 19
 #define LFUN_INDEX 20
 #define LFUN_ASSIGN_INDEX 21
+#define LFUN_ARROW 22
+#define LFUN_ASSIGN_ARROW 23
 
-#define NUM_LFUNS 22
+#define NUM_LFUNS 24
 
 extern char *lfun_names[];
 
-- 
GitLab