diff --git a/src/docode.c b/src/docode.c
index fb882687a0cfcb94d9f0996a3b35211ccf3147da..ed41649493a3f49d03b471ab552eebd39a5e2252 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.33 1998/03/01 11:40:46 hubbe Exp $");
+RCSID("$Id: docode.c,v 1.34 1998/03/31 21:52:16 hubbe Exp $");
 #include "las.h"
 #include "program.h"
 #include "language.h"
@@ -989,11 +989,46 @@ static int do_docode2(node *n,int flags)
       fatal("Bugg in F_ARROW, index not string.");
     if(flags & DO_LVALUE)
     {
-      /* FIXME!!!! */
+      /* FIXME!!!! ??? I wonder what needs fixing... /Hubbe */
       tmp1=do_docode(CAR(n), 0);
       emit(F_ARROW_STRING, store_prog_string(CDR(n)->u.sval.u.string));
       return 2;
     }else{
+      struct program *p;
+      if(CAR(n) &&
+	 CDR(n) &&
+	 EXTRACT_UCHAR(CAR(n)->type->str)==T_OBJECT &&
+	 (tmp2=EXTRACT_INT(CAR(n)->type->str+1)) &&
+	 (p=id_to_program(tmp2)) &&
+	 (FIND_LFUN(p,LFUN_ARROW)==-1) &&
+	 CDR(n)->token == F_CONSTANT &&
+	 CDR(n)->u.sval.type==T_STRING)
+      {
+	tmp3=find_shared_string_identifier(CDR(n)->u.sval.u.string,p);
+	if(tmp3==-1)
+	{
+	  yywarning("Accessing a non-existant identifier");
+	  DO_CODE_BLOCK(CAR(n));
+	  emit(F_NUMBER,0);
+	  return 1;
+	}else{
+	  struct identifier *i=ID_FROM_INT(p,tmp3);
+	  if(IDENTIFIER_IS_FUNCTION(i->identifier_flags))
+	  {
+	    tmp1=do_docode(CAR(n), DO_NOT_COPY);
+	    emit(F_STRICT_ARROW, tmp3);
+	    emit(F_DATA, tmp2);
+	    return tmp1;
+	  }
+	  if(IDENTIFIER_IS_VARIABLE(i->identifier_flags))
+	  {
+	    tmp1=do_docode(CAR(n), DO_NOT_COPY);
+	    emit(F_STRICT_ARROW_VARIABLE, tmp3);
+	    emit(F_DATA, tmp2);
+	    return tmp1;
+	  }
+	}
+      }
       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))
diff --git a/src/interpret.c b/src/interpret.c
index 666a33f7f4bfe042172d5603cb6a9771212ac829..81256f565b6411880baceb385524056b27bcb98a 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.71 1998/03/26 05:37:50 hubbe Exp $");
+RCSID("$Id: interpret.c,v 1.72 1998/03/31 21:52:17 hubbe Exp $");
 #include "interpret.h"
 #include "object.h"
 #include "program.h"
@@ -580,6 +580,8 @@ static int eval_instruction(unsigned char *pc)
       CASE(F_NEG_NUMBER); push_int(-GET_ARG()); break;
 
       /* The rest of the basic 'push value' instructions */	
+
+      CASE(F_MARK_AND_STRING); *(mark_sp++)=sp;
       CASE(F_STRING);
       copy_shared_string(sp->u.string,fp->context.prog->strings[GET_ARG()]);
       sp->type=T_STRING;
@@ -757,6 +759,20 @@ static int eval_instruction(unsigned char *pc)
       fp->locals[instr+1].u.integer=0;
       break;
 
+      CASE(F_CLEAR_4_LOCAL);
+      {
+	int e;
+	instr=GET_ARG();
+	free_svalues(fp->locals + instr, 4, -1);
+	for(e=0;e<4;e++)
+	{
+	  fp->locals[instr+e].type=T_INT;
+	  fp->locals[instr+e].subtype=0;
+	  fp->locals[instr+e].u.integer=0;
+	}
+	break;
+      }
+
       CASE(F_CLEAR_LOCAL);
       instr=GET_ARG();
       free_svalue(fp->locals + instr);
@@ -1038,10 +1054,18 @@ static int eval_instruction(unsigned char *pc)
       pop_n_elems(3);
       break;
 
+    CASE(F_APPLY_ASSIGN_LOCAL);
+      strict_apply_svalue(fp->context.prog->constants + GET_ARG(), sp - *--mark_sp );
+      /* Fall through */
+
       CASE(F_ASSIGN_LOCAL);
       assign_svalue(fp->locals+GET_ARG(),sp-1);
       break;
 
+    CASE(F_APPLY_ASSIGN_LOCAL_AND_POP);
+      strict_apply_svalue(fp->context.prog->constants + GET_ARG(), sp - *--mark_sp );
+      /* Fall through */
+
       CASE(F_ASSIGN_LOCAL_AND_POP);
       instr=GET_ARG();
       free_svalue(fp->locals+instr);
@@ -1101,6 +1125,7 @@ static int eval_instruction(unsigned char *pc)
       CASE(F_POP_N_ELEMS); pop_n_elems(GET_ARG()); break;
       CASE(F_MARK2); *(mark_sp++)=sp;
       CASE(F_MARK); *(mark_sp++)=sp; break;
+      CASE(F_MARK_X); *(mark_sp++)=sp-GET_ARG(); break;
 
       CASE(F_CLEAR_STRING_SUBTYPE);
       if(sp[-1].type==T_STRING) sp[-1].subtype=0;
@@ -1131,6 +1156,16 @@ static int eval_instruction(unsigned char *pc)
       pop_stack();
       break;
 
+      CASE(F_BRANCH_IF_LOCAL);
+      instr=GET_ARG();
+      if(IS_ZERO(fp->locals + instr))
+      {
+	pc+=sizeof(INT32);
+      }else{
+	DOJUMP();
+      }
+      break;
+
       CJUMP(F_BRANCH_WHEN_EQ, is_eq);
       CJUMP(F_BRANCH_WHEN_NE,!is_eq);
       CJUMP(F_BRANCH_WHEN_LT, is_lt);
@@ -1265,6 +1300,12 @@ static int eval_instruction(unsigned char *pc)
 	return args+1;
       }
 
+      CASE(F_RETURN_LOCAL);
+      instr=GET_ARG();
+      pop_n_elems(sp-1 - (fp->locals+instr));
+      print_return_value();
+      goto do_return;
+
       CASE(F_RETURN_1);
       push_int(1);
       goto do_return;
@@ -1353,12 +1394,50 @@ static int eval_instruction(unsigned char *pc)
       push_array_items(sp->u.array);
       break;
 
+      CASE(F_STRICT_ARROW);
+      if(sp[-1].type != T_OBJECT)
+	error("Expected object for first argument to `->\n");
+      if(!sp[-1].u.object->prog)
+	error("`-> on destructed object.\n");
+      sp[-1].subtype=GET_ARG();
+      if(sp[-1].u.object->prog->id != EXTRACT_INT(pc))
+	error("`->: Object not of specified type.\n");
+      sp[-1].type=T_FUNCTION;
+      pc+=sizeof(INT32);
+      break;
+
+      CASE(F_STRICT_ARROW_VARIABLE);
+      if(sp[-1].type != T_OBJECT)
+	error("Expected object for first argument to `->\n");
+      if(!sp[-1].u.object->prog)
+	error("`-> on destructed object.\n");
+      instr=GET_ARG();
+      if(sp[-1].u.object->prog->id != EXTRACT_INT(pc))
+	error("`->: Object not of specified type.\n");
+      pc+=sizeof(INT32);
+      low_object_index_no_free(sp,sp[-1].u.object,instr);
+      free_object(sp[-1].u.object);
+      sp[-1]=*sp;
+      break;
+
+      CASE(F_LOCAL_LOCAL_INDEX);
+      {
+	struct svalue *s=fp->locals+GET_ARG();
+	if(s->type == T_STRING) s->subtype=0;
+	sp++->type=T_INT;
+	index_no_free(sp-1,fp->locals+GET_ARG(),s);
+	break;
+      }
+
       CASE(F_LOCAL_INDEX);
-      assign_svalue_no_free(sp++,fp->locals+GET_ARG());
-      if(sp[-1].type == T_STRING)
-	sp[-1].subtype=0;
-      print_return_value();
-      goto do_index;
+      {
+	struct svalue tmp,*s=fp->locals+GET_ARG();
+	if(s->type == T_STRING) s->subtype=0;
+	index_no_free(&tmp,sp-1,s);
+	free_svalue(sp-1);
+	sp[-1]=tmp;
+	break;
+      }
 
       CASE(F_POS_INT_INDEX);
       push_int(GET_ARG());
diff --git a/src/language.yacc b/src/language.yacc
index 4bfa60e1605264be49b0af1ccb0f4259c7a635c7..a224cb26bca20853c2643f3040e0f02280873534 100644
--- a/src/language.yacc
+++ b/src/language.yacc
@@ -10,20 +10,24 @@
  */
 %token F_PREFIX_256 F_PREFIX_512 F_PREFIX_768 F_PREFIX_1024
 %token F_PREFIX_CHARX256 F_PREFIX_WORDX256 F_PREFIX_24BITX256
-%token F_POP_VALUE F_POP_N_ELEMS F_MARK F_MARK2 F_LDA
+%token F_POP_VALUE F_POP_N_ELEMS F_MARK F_MARK2 F_MARK_X F_LDA
 %token F_CALL_LFUN F_CALL_LFUN_AND_POP F_CALL_LFUN_AND_RETURN
 %token F_APPLY F_APPLY_AND_POP F_MARK_APPLY F_MARK_APPLY_POP
-%token F_APPLY_AND_RETURN
+%token F_APPLY_AND_RETURN F_MARK_AND_STRING
+%token F_APPLY_ASSIGN_LOCAL F_APPLY_ASSIGN_LOCAL_AND_POP
 
 %token F_BRANCH F_BRANCH_WHEN_ZERO F_BRANCH_WHEN_NON_ZERO
 %token F_BRANCH_WHEN_LT F_BRANCH_WHEN_GT
 %token F_BRANCH_WHEN_LE F_BRANCH_WHEN_GE
 %token F_BRANCH_WHEN_EQ F_BRANCH_WHEN_NE
+%token F_BRANCH_IF_LOCAL
 %token F_INC_LOOP F_DEC_LOOP
 %token F_INC_NEQ_LOOP F_DEC_NEQ_LOOP
 
 %token F_INDEX F_ARROW F_INDIRECT F_STRING_INDEX F_LOCAL_INDEX
-%token F_POS_INT_INDEX F_NEG_INT_INDEX
+%token F_LOCAL_LOCAL_INDEX
+%token F_POS_INT_INDEX F_NEG_INT_INDEX F_STRICT_ARROW
+%token F_STRICT_ARROW_VARIABLE
 %token F_LTOSVAL F_LTOSVAL2
 %token F_PUSH_ARRAY 
 %token F_RANGE F_COPY_VALUE
@@ -35,7 +39,8 @@
 %token F_GLOBAL F_GLOBAL_LVALUE
 %token F_LOCAL F_2_LOCALS F_LOCAL_LVALUE F_MARK_AND_LOCAL
 %token F_EXTERNAL F_EXTERNAL_LVALUE
-%token F_CLEAR_LOCAL F_CLEAR_2_LOCAL F_CLEAR_STRING_SUBTYPE
+%token F_CLEAR_LOCAL F_CLEAR_2_LOCAL F_CLEAR_4_LOCAL
+%token 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
 /*
@@ -45,7 +50,8 @@
 %token F_INC F_DEC F_POST_INC F_POST_DEC F_INC_AND_POP F_DEC_AND_POP
 %token F_INC_LOCAL F_INC_LOCAL_AND_POP F_POST_INC_LOCAL
 %token F_DEC_LOCAL F_DEC_LOCAL_AND_POP F_POST_DEC_LOCAL
-%token F_RETURN F_DUMB_RETURN F_RETURN_0 F_RETURN_1 F_THROW_ZERO
+%token F_RETURN F_DUMB_RETURN F_RETURN_0 F_RETURN_1 F_RETURN_LOCAL
+%token F_THROW_ZERO
 
 %token F_ASSIGN F_ASSIGN_AND_POP
 %token F_ASSIGN_LOCAL F_ASSIGN_LOCAL_AND_POP
@@ -89,7 +95,7 @@
 %token F_DO
 %token F_DOT_DOT
 %token F_DOT_DOT_DOT
-%token F_PREDEF
+%token F_REDEF
 %token F_EFUN_CALL
 %token F_ELSE
 %token F_FLOAT_ID
@@ -120,6 +126,7 @@
 %token F_PRIVATE
 %token F_PROGRAM_ID
 %token F_PROTECTED
+%token F_PREDEF
 %token F_PUBLIC
 %token F_RSH_EQ
 %token F_STATIC
@@ -139,6 +146,7 @@
 %token F_POINTER
 %token F_LABEL
 %token F_BYTE
+%token F_DATA
 
 %token F_MAX_INSTR
 
@@ -161,7 +169,7 @@
 /* This is the grammar definition of Pike. */
 
 #include "global.h"
-RCSID("$Id: language.yacc,v 1.66 1998/03/04 23:49:54 hubbe Exp $");
+RCSID("$Id: language.yacc,v 1.67 1998/03/31 21:52:19 hubbe Exp $");
 #ifdef HAVE_MEMORY_H
 #include <memory.h>
 #endif
diff --git a/src/lex.c b/src/lex.c
index ec595c996f7f7fb719a127028da2e4b423d6ec4c..6eaac9eff4dac330ac6ba5cb560f570f5c113fb3 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.45 1998/03/22 06:19:37 hubbe Exp $");
+RCSID("$Id: lex.c,v 1.46 1998/03/31 21:52:20 hubbe Exp $");
 #include "language.h"
 #include "array.h"
 #include "lex.h"
@@ -38,6 +38,10 @@ RCSID("$Id: lex.c,v 1.45 1998/03/22 06:19:37 hubbe Exp $");
 
 #define LEXDEBUG 0
 
+#ifdef INSTR_PROFILING
+int last_instruction=0;
+#endif
+
 void exit_lex(void)
 {
 #ifdef DEBUG
@@ -52,6 +56,16 @@ void exit_lex(void)
 	      (long)instrs[e].runs,
 	      (long)instrs[e].compiles);
     }
+
+#ifdef INSTR_PROFILING
+    for(e=0;e<F_MAX_OPCODE-F_OFFSET;e++)
+    {
+      int d;
+      for(d=0;d<256;d++)
+	if(instrs[e].reruns[d])
+	  fprintf(stderr,"%010ld::%s - %s\n",instrs[e].reruns[d],low_get_f_name(e+F_OFFSET,0),low_get_f_name(d+F_OFFSET,0));
+    }
+#endif
   }
 #endif
 }
@@ -115,13 +129,16 @@ struct keyword instr_names[]=
 { "for",		F_FOR },
 { "global",		F_GLOBAL, I_HASARG },
 { "index",              F_INDEX },
-{ "->",                 F_ARROW, I_HASARG },
+{ "->x",                F_ARROW, I_HASARG },
+{ "object(const)->func",      F_STRICT_ARROW, I_HASARG },
+{ "object(const)->var",      F_STRICT_ARROW_VARIABLE, I_HASARG },
 { "clear string subtype", F_CLEAR_STRING_SUBTYPE },
 { "arrow string",       F_ARROW_STRING, I_HASARG },
 { "indirect",		F_INDIRECT },
 
 { "branch",             F_BRANCH, I_ISJUMP },
 { "branch non zero",	F_BRANCH_WHEN_NON_ZERO, I_ISJUMP },	
+{ "branch if local",	F_BRANCH_IF_LOCAL, I_HASARG },	
 { "branch when zero",	F_BRANCH_WHEN_ZERO, I_ISJUMP },	
 { "branch if <",	F_BRANCH_WHEN_LT, I_ISJUMP },
 { "branch if >",	F_BRANCH_WHEN_GT, I_ISJUMP },
@@ -139,7 +156,8 @@ struct keyword instr_names[]=
 { "==&&",               F_EQ_AND, I_ISJUMP },
 { "catch",		F_CATCH, I_ISJUMP },
 { "foreach",		F_FOREACH, I_ISJUMP },
-{ "data",		F_POINTER, I_ISPOINTER },
+{ "pointer",		F_POINTER, I_ISPOINTER },
+{ "data",		F_DATA, I_DATA },
 
 { "local function call",F_CALL_LFUN, I_HASARG },
 { "local function call and pop",F_CALL_LFUN_AND_POP, I_HASARG },
@@ -153,6 +171,7 @@ struct keyword instr_names[]=
 { "lvalue to svalue",	F_LTOSVAL },	
 { "lvalue_list",	F_LVALUE_LIST },	
 { "[ lvalues ]",	F_ARRAY_LVALUE, I_HASARG },	
+{ "mark sp-X",          F_MARK_X, I_HASARG },
 { "mark",               F_MARK },
 { "mark mark",          F_MARK2 },
 { "negative number",	F_NEG_NUMBER, I_HASARG },
@@ -166,6 +185,7 @@ struct keyword instr_names[]=
 { "return",		F_RETURN },
 { "return 0",		F_RETURN_0 },
 { "return 1",		F_RETURN_1 },
+{ "return local",	F_RETURN_LOCAL, I_HASARG },
 { "sscanf",		F_SSCANF, I_HASARG },	
 { "string",             F_STRING, I_HASARG },
 { "switch",		F_SWITCH, I_HASARG },
@@ -183,6 +203,7 @@ struct keyword instr_names[]=
 { "call",		F_APPLY, I_HASARG },
 { "clear local",	F_CLEAR_LOCAL, I_HASARG },
 { "clear 2 local",	F_CLEAR_2_LOCAL, I_HASARG },
+{ "clear 4 local",	F_CLEAR_4_LOCAL, I_HASARG },
 { "++local",		F_INC_LOCAL, I_HASARG },
 { "++local and pop",	F_INC_LOCAL_AND_POP, I_HASARG },
 { "local++",		F_POST_INC_LOCAL, I_HASARG },
@@ -194,6 +215,7 @@ struct keyword instr_names[]=
 { "throw(0)",		F_THROW_ZERO },
 { "string index",       F_STRING_INDEX, I_HASARG },
 { "local index",        F_LOCAL_INDEX, I_HASARG },
+{ "local local index",  F_LOCAL_LOCAL_INDEX, I_HASARG },
 { "int index",          F_POS_INT_INDEX, I_HASARG },
 { "-int index",         F_NEG_INT_INDEX, I_HASARG },
 { "apply and pop",      F_APPLY_AND_POP, I_HASARG },
@@ -202,9 +224,12 @@ struct keyword instr_names[]=
 { "nop",                F_NOP },
 { "add integer",        F_ADD_INT, I_HASARG },
 { "add -integer",       F_ADD_NEG_INT, I_HASARG },
+{ "mark & string",      F_MARK_AND_STRING, I_HASARG },
 { "mark & call",        F_MARK_APPLY, I_HASARG },
 { "mark, call & pop",   F_MARK_APPLY_POP, I_HASARG },
 { "apply and return",   F_APPLY_AND_RETURN, I_HASARG },
+{ "apply, assign local and pop",   F_APPLY_ASSIGN_LOCAL_AND_POP, I_HASARG },
+{ "apply & assign local",   F_APPLY_ASSIGN_LOCAL, I_HASARG },
 { "call lfun & return", F_CALL_LFUN_AND_RETURN, I_HASARG },
 { "call function",      F_CALL_FUNCTION, 0 },
 { "call function & return", F_CALL_FUNCTION_AND_RETURN, 0 },
diff --git a/src/lex.h b/src/lex.h
index ece7851d1fe78125f7de8b7dd7e67347b9c067af..aa4e1b1927b652c66a9de6be20a4a74c22ecf541 100644
--- a/src/lex.h
+++ b/src/lex.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: lex.h,v 1.10 1998/03/28 15:13:07 grubba Exp $
+ * $Id: lex.h,v 1.11 1998/03/31 21:52:21 hubbe Exp $
  */
 #ifndef LEX_H
 #define LEX_H
@@ -24,10 +24,22 @@ struct keyword
 #define I_JUMP 4
 #define I_ISPOINTER 3
 #define I_ISJUMP 7
+#define I_DATA 9
+
+#ifdef DEBUG
+#define INSTR_PROFILING
+#endif
+
+#ifdef INSTR_PROFILING
+extern int last_instruction;
+#endif
 
 struct instr
 {
 #ifdef DEBUG
+#ifdef INSTR_PROFILING
+  long reruns[256];
+#endif
   long runs;
   long compiles;
 #endif
@@ -37,7 +49,11 @@ struct instr
 
 #ifdef DEBUG
 #define ADD_COMPILED(X) instrs[(X)-F_OFFSET].compiles++
+#ifdef INSTR_PROFILING
+#define ADD_RUNNED(X) do { int _x=(X)-F_OFFSET; instrs[last_instruction].reruns[_x]++; instrs[last_instruction=_x].runs++; } while(0)
+#else
 #define ADD_RUNNED(X) instrs[(X)-F_OFFSET].runs++
+#endif
 #else
 #define ADD_COMPILED(X)
 #define ADD_RUNNED(X)
diff --git a/src/main.c b/src/main.c
index 56c9cdf740b16c04486d675719e8bbfd2f290b99..871846e28b2b3a890d2958269b623ccfcd68665b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: main.c,v 1.43 1998/03/22 06:20:44 hubbe Exp $");
+RCSID("$Id: main.c,v 1.44 1998/03/31 21:52:21 hubbe Exp $");
 #include "fdlib.h"
 #include "backend.h"
 #include "module.h"
@@ -199,9 +199,14 @@ int dbm_main(int argc, char **argv)
 	    case 's':
 	      debug_options|=DEBUG_SIGNALS;
 	      p++;
-	      if(p[1]) goto more_d_flags;
+	      d_flag--;
+	      goto more_d_flags;
+
+	    case 't':
+	      debug_options|=NO_TAILRECURSION;
 	      p++;
-	      break;
+	      d_flag--;
+	      goto more_d_flags;
 
 	    default:
 	      d_flag++,p++;
diff --git a/src/main.h b/src/main.h
index 31ceea31b78d54096d7852edb6ba0509c499dff9..f5f80f180dfd779785d552307450c477c01410ee 100644
--- a/src/main.h
+++ b/src/main.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: main.h,v 1.7 1998/03/28 15:12:14 grubba Exp $
+ * $Id: main.h,v 1.8 1998/03/31 21:52:22 hubbe Exp $
  */
 #ifndef MAIN_H
 #define MAIN_H
@@ -15,6 +15,7 @@
 extern int d_flag, t_flag, a_flag, l_flag, c_flag, p_flag, debug_options;
 
 #define DEBUG_SIGNALS 1
+#define NO_TAILRECURSION 2
 
 /* Prototypes begin here */
 struct callback *add_post_master_callback(callback_func call,
diff --git a/src/peep.c b/src/peep.c
index 4369524f92c7f6c616264009fa8a56989ba19eb9..c730f23c385ff766270584098a80559c1a5ea6d7 100644
--- a/src/peep.c
+++ b/src/peep.c
@@ -12,7 +12,7 @@
 #include "peep.h"
 #include "dmalloc.h"
 
-RCSID("$Id: peep.c,v 1.19 1998/03/28 15:11:56 grubba Exp $");
+RCSID("$Id: peep.c,v 1.20 1998/03/31 21:52:23 hubbe Exp $");
 
 struct p_instr_s
 {
@@ -258,6 +258,10 @@ void assemble(void)
       add_to_program(c->arg);
       break;
 
+    case F_DATA:
+      ins_int(c->arg, (void(*)(char))add_to_program);
+      break;
+
     case F_LABEL:
 #ifdef DEBUG
       if(c->arg > max_label || c->arg < 0)
@@ -283,9 +287,9 @@ void assemble(void)
 	jumps[c->arg]=tmp;
 	break;
 
-      case I_HASARG:
-	ins_f_byte_with_arg(c->opcode, c->arg);
-	break;
+	case I_HASARG:
+	  ins_f_byte_with_arg(c->opcode, c->arg);
+	  break;
 
       case 0:
 	ins_f_byte(c->opcode);
@@ -345,7 +349,6 @@ int insopt(int f, INT32 b, int cl, struct pike_string *cf)
   {
     MEMMOVE(p-fifo_len+1,p-fifo_len,fifo_len*sizeof(p_instr));
     p-=fifo_len;
-    fifo_len++;
   }
 
 #ifdef DEBUG
@@ -367,7 +370,7 @@ int insopt2(int f, int cl, struct pike_string *cf)
   if(hasarg(f))
     fatal("hasarg() is wrong!\n");
 #endif
-  return insert_opcode(f,0,cl, cf);
+  return insopt(f,0,cl, cf);
 }
 
 
diff --git a/src/peep.in b/src/peep.in
index 01b470eacb9c7be03a94606d4f9085ab7ca3bc97..80526b2a3f2dabdddff8cab4cdb4c9a6eda60bd6 100644
--- a/src/peep.in
+++ b/src/peep.in
@@ -1,5 +1,5 @@
 #
-# $Id: peep.in,v 1.12 1998/03/28 15:47:46 grubba Exp $
+# $Id: peep.in,v 1.13 1998/03/31 21:52:23 hubbe Exp $
 #
 NOP :
 POP_N_ELEMS (0) : 
@@ -34,6 +34,7 @@ NEGATE CONST1 SUBTRACT : COMPL
 CONST0 ASSIGN_LOCAL_AND_POP : CLEAR_LOCAL($2a)
 CLEAR_LOCAL NUMBER(0) ASSIGN_LOCAL_AND_POP ($1a) : CLEAR_LOCAL($1a)
 CLEAR_LOCAL NUMBER(0) ASSIGN_LOCAL_AND_POP ($1a+1) : CLEAR_2_LOCAL($1a)
+CLEAR_2_LOCAL CLEAR_2_LOCAL($1a+2) : CLEAR_4_LOCAL($1a)
 
 #CONST_1 MULTIPLY : NEGATE
 #CONST0 MULTIPLY : POP_VALUE CONST0
@@ -60,6 +61,8 @@ NOT BRANCH_WHEN_ZERO: BRANCH_WHEN_NON_ZERO($2a)
 BRANCH !LABEL : BRANCH($1a)
 RETURN !LABEL : RETURN
 RETURN_0 !LABEL : RETURN_0
+RETURN_1 !LABEL : RETURN_1
+RETURN_LOCAL !LABEL : RETURN_LOCAL($1a)
 BRANCH LABEL ($1a) : LABEL ($1a)
 
 LOCAL_LVALUE INC : INC_LOCAL ($1a)
@@ -74,11 +77,7 @@ LOCAL_LVALUE DEC_AND_POP : DEC_LOCAL_AND_POP ($1a)
 DEC_LOCAL POP_VALUE : DEC_LOCAL_AND_POP ($1a)
 POST_DEC_LOCAL POP_VALUE : DEC_LOCAL_AND_POP ($1a)
 
-ASSIGN_LOCAL_AND_POP LOCAL ($1a) : ASSIGN_LOCAL ($1a)
 ASSIGN_LOCAL_AND_POP LOCAL ($1a) RETURN : RETURN
-ASSIGN_GLOBAL_AND_POP GLOBAL ($1a) : ASSIGN_GLOBAL ($1a)
-DEC_LOCAL_AND_POP LOCAL ($1a) : DEC_LOCAL ($1a)
-INC_LOCAL_AND_POP LOCAL ($1a) : INC_LOCAL ($1a)
 
 GLOBAL_LVALUE INC_AND_POP GLOBAL($1a): GLOBAL_LVALUE($1a) INC
 GLOBAL_LVALUE DEC_AND_POP GLOBAL($1a): GLOBAL_LVALUE($1a) DEC
@@ -114,9 +113,11 @@ GE NOT: LT
 
 LOCAL LOCAL [$2a<256 && $3o != F_SIZEOF && $3o != F_INDEX ]: 2_LOCALS ($1a) BYTE ($2a)
 MARK LOCAL [ $3o != F_SIZEOF && $3o != F_INDEX ]: MARK_AND_LOCAL ($2a)
+MARK STRING : MARK_AND_STRING($2a)
 LOCAL SIZEOF: SIZEOF_LOCAL ($1a)
 STRING INDEX: STRING_INDEX ($1a)
 LOCAL INDEX: LOCAL_INDEX ($1a)
+LOCAL LOCAL INDEX: LOCAL_LOCAL_INDEX($2a) BYTE($1a)
 CONST0 INDEX: POS_INT_INDEX (0)
 CONST_1 INDEX: NEG_INT_INDEX (1)
 CONST1 INDEX: POS_INT_INDEX (1)
@@ -154,6 +155,49 @@ NUMBER [$1a < 0] SUBTRACT : ADD_INT (-$1a)
 LTOSVAL2 ADD ASSIGN_AND_POP : ADD_TO_AND_POP
 LTOSVAL ADD ASSIGN_AND_POP : ADD_TO_AND_POP
 
-APPLY RETURN : APPLY_AND_RETURN($1a)
-CALL_FUNCTION RETURN : CALL_FUNCTION_AND_RETURN
-CALL_LFUN RETURN : CALL_LFUN_AND_RETURN($1a)
+APPLY [ !(debug_options & NO_TAILRECURSION) ] RETURN : APPLY_AND_RETURN($1a)
+CALL_FUNCTION [ !(debug_options & NO_TAILRECURSION) ] RETURN : CALL_FUNCTION_AND_RETURN
+CALL_LFUN [ !(debug_options & NO_TAILRECURSION) ] RETURN : CALL_LFUN_AND_RETURN($1a)
+
+LOCAL RETURN : RETURN_LOCAL($1a)
+APPLY ASSIGN_LOCAL_AND_POP : APPLY_ASSIGN_LOCAL_AND_POP($1a) BYTE($2a)
+ASSIGN_LOCAL_AND_POP INC_LOCAL_AND_POP($1a) : ADD_INT(1) ASSIGN_LOCAL_AND_POP($1a)
+ASSIGN_LOCAL_AND_POP DEC_LOCAL_AND_POP($1a) : ADD_NEG_INT(1) ASSIGN_LOCAL_AND_POP($1a)
+NUMBER ADD_INT: NUMBER($1a+$2a)
+NUMBER ADD_NEG_INT: NUMBER($1a-$2a)
+NEG_NUMBER ADD_INT: NUMBER($-1a+$2a)
+NEG_NUMBER ADD_NEG_INT: NUMBER(-$1a-$2a)
+
+LOCAL BRANCH_WHEN_NON_ZERO : BRANCH_IF_LOCAL($1a) POINTER($2a)
+
+DEC_LOCAL_AND_POP LOCAL ($1a) : DEC_LOCAL ($1a)
+INC_LOCAL_AND_POP LOCAL ($1a) : INC_LOCAL ($1a)
+ASSIGN_LOCAL_AND_POP LOCAL($1a) : ASSIGN_LOCAL($1a)
+ASSIGN_GLOBAL_AND_POP GLOBAL($1a) : ASSIGN_GLOBAL($1a)
+APPLY_ASSIGN_LOCAL_AND_POP BYTE LOCAL ($2a) : APPLY_ASSIGN_LOCAL($1a) BYTE($2a)
+
+DEC_LOCAL_AND_POP MARK_AND_LOCAL ($1a) : MARK DEC_LOCAL ($1a)
+INC_LOCAL_AND_POP MARK_AND_LOCAL ($1a) : MARK INC_LOCAL ($1a)
+ASSIGN_GLOBAL_AND_POP MARK GLOBAL($1a) : MARK_X(1) ASSIGN_GLOBAL($1a)
+ASSIGN_LOCAL_AND_POP MARK_AND_LOCAL($1a) : MARK_X(1) ASSIGN_LOCAL($1a)
+APPLY_ASSIGN_LOCAL_AND_POP BYTE MARK_AND_LOCAL ($2a) : APPLY_ASSIGN_LOCAL($1a) BYTE($2a) MARK_X(1) 
+
+ASSIGN_LOCAL ASSIGN_LOCAL($1a) : ASSIGN_LOCAL($1a)
+
+# MARK_X rules
+MARK_X(0) : MARK
+LOCAL MARK_X [$2a>0] : MARK_X($2a-1) LOCAL($1a)
+STRING MARK_X [$2a>0] : MARK_X($2a-1) STRING($1a)
+NUMBER MARK_X [$2a>0] : MARK_X($2a-1) NUMBER($1a)
+CONST0 MARK_X [$2a>0] : MARK_X($2a-1) CONST0
+CONST1 MARK_X [$2a>0] : MARK_X($2a-1) CONST1
+CONST_1 MARK_X [$2a>0] : MARK_X($2a-1) CONST_1
+NEG_NUMBER MARK_X [$2a>0] : MARK_X($2a-1) NEG_NUMBER($1a)
+GLOBAL MARK_X [$2a>0] : MARK_X($2a-1) GLOBAL($1a)
+MARK_APPLY MARK_X [$2a>0] : MARK_X($2a-1) MARK_APPLY($1a)
+CONSTANT MARK_X [$2a>0] : MARK_X($2a-1) CONSTANT($1a)
+FLOAT MARK_X [$2a>0] : MARK_X($2a-1) FLOAT($1a)
+LFUN MARK_X [$2a>0] : MARK_X($2a-1) LFUN($1a)
+LTOSVAL MARK_X [$2a>0] : MARK_X($2a-1) LTOSVAL
+LOCAL_LVALUE MARK_X [$2a>1] : MARK_X($2a-2) LOCAL_LVALUE($1a)
+2_LOCALS BYTE MARK_X [$2a>0] : LOCAL($1a) MARK_X($3a-1) LOCAL($2a)