diff --git a/src/ChangeLog b/src/ChangeLog
index 41124fce848bf58e67ff11e10cc336c510793fce..4d038a46b31f727bff532abd4d01f6a0061b1ace 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,13 @@
+Mon Mar 10 16:58:06 1997  Fredrik Hubinette  <hubbe@cytocin.hubbe.net>
+
+	* docode.c (do_cond_jump): optimized || and &&
+	* program.c (add_constant): constants are now redefinable
+	* interpret.c: F_EQ_OR now works, added F_EQ_AND
+
+Sun Mar  9 01:44:03 1997  Fredrik Hubinette  <hubbe@cytocin.hubbe.net>
+
+	* peephole optimized fixed and improved
+
 Sat Mar  8 04:31:29 1997  Fredrik Hubinette  <hubbe@cytocin.hubbe.net>
 
 	* added new efuns `[] and `->
diff --git a/src/docode.c b/src/docode.c
index 12e2c9f2aee32e4156e2b728c04a8908c7d93429..9cff5c51433b611b710d527654f76b74e94e266b 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.13 1997/03/09 09:11:10 hubbe Exp $");
+RCSID("$Id: docode.c,v 1.14 1997/03/11 03:36:39 hubbe Exp $");
 #include "las.h"
 #include "program.h"
 #include "language.h"
@@ -158,8 +158,6 @@ int do_docode(node *n,INT16 flags)
 }
 
 
-void do_jump_when_zero(node *n,int j);
-
 static int is_efun(node *n, c_fun fun)
 {
   return n && n->token == F_CONSTANT &&
@@ -167,102 +165,66 @@ static int is_efun(node *n, c_fun fun)
     n->u.sval.u.efun->function == fun;
 }
 
-void do_jump_when_non_zero(node *n,int j)
+void do_cond_jump(node *n, int label, int iftrue, int flags)
 {
-  if(!node_is_tossable(n))
+  iftrue=!!iftrue;
+  if((flags & DO_POP) && node_is_tossable(n))
   {
-    if(node_is_true(n))
+    int t,f;
+    t=!!node_is_true(n);
+    f=!!node_is_false(n);
+    if(t || f)
     {
-      do_jump(F_BRANCH,j);
+      if(t == iftrue) do_jump(F_BRANCH, label);
       return;
     }
-
-    if(node_is_false(n))
-      return;
   }
 
   switch(n->token)
   {
-  case F_APPLY:
-    if(is_efun(CAR(n), f_not))
-    {
-      do_jump_when_zero(CDR(n), j);
-      return;
-    }
-    break;
-      
-  case F_NOT:
-    do_jump_when_zero(CAR(n), j);
-    return;
-
   case F_LAND:
-  {
-    int tmp=alloc_label();
-    do_jump_when_zero(CAR(n), tmp);
-    do_jump_when_non_zero(CDR(n), j);
-    emit(F_LABEL,tmp);
-    return;
-  }
-    
   case F_LOR:
-    do_jump_when_non_zero(CAR(n), j);
-    do_jump_when_non_zero(CDR(n), j);
-    return;
-  }
-
-  if(do_docode(n, DO_NOT_COPY)!=1)
-    fatal("Infernal compiler skiterror.\n");
-  do_jump(F_BRANCH_WHEN_NON_ZERO,j);
-}
-
-void do_jump_when_zero(node *n,int j)
-{
-  if(!node_is_tossable(n))
-  {
-    if(node_is_true(n))
-      return;
-
-    if(node_is_false(n))
+    if(iftrue == (n->token==F_LAND))
     {
-      do_jump(F_BRANCH,j);
-      return;
+      int tmp=alloc_label();
+      do_cond_jump(CAR(n), tmp, !iftrue, flags | DO_POP);
+      do_cond_jump(CDR(n), label, iftrue, flags);
+      emit(F_LABEL,tmp);
+    }else{
+      do_cond_jump(CAR(n), label, iftrue, flags);
+      do_cond_jump(CDR(n), label, iftrue, flags);
     }
-  }
-
-  switch(n->token)
-  {
+    return;
+    
   case F_APPLY:
-    if(is_efun(CAR(n), f_not))
-    {
-      do_jump_when_non_zero(CDR(n), j);
-      return;
-    }
-    break;
+    if(!is_efun(CAR(n), f_not)) break;
 
   case F_NOT:
-    do_jump_when_non_zero(CAR(n), j);
-    return;
-
-  case F_LOR:
-  {
-    int tmp=alloc_label();
-    do_jump_when_non_zero(CAR(n), tmp);
-    do_jump_when_zero(CDR(n), j);
-    emit(F_LABEL,tmp);
+    if(!(flags & DO_POP)) break;
+    do_cond_jump(CDR(n), label , !iftrue, flags | DO_NOT_COPY);
     return;
   }
 
-  case F_LAND:
-    do_jump_when_zero(CAR(n), j);
-    do_jump_when_zero(CDR(n), j);
-    return;
-  }
-
-  if(do_docode(n, DO_NOT_COPY)!=1)
+  if(do_docode(n, flags&DO_NOT_COPY)!=1)
     fatal("Infernal compiler skiterror.\n");
-  do_jump(F_BRANCH_WHEN_ZERO,j);
+  
+  if(flags & DO_POP)
+  {
+    if(iftrue)
+      do_jump(F_BRANCH_WHEN_NON_ZERO, label);
+    else
+      do_jump(F_BRANCH_WHEN_ZERO, label);
+  }else{
+    if(iftrue)
+      do_jump(F_LOR, label);
+    else
+      do_jump(F_LAND, label);
+  }
 }
 
+#define do_jump_when_zero(N,L) do_cond_jump(N,L,0,DO_POP|DO_NOT_COPY)
+#define do_jump_when_non_zero(N,L) do_cond_jump(N,L,1,DO_POP|DO_NOT_COPY)
+
 static INT32 count_cases(node *n)
 {
   INT32 ret;
@@ -503,11 +465,9 @@ static int do_docode2(node *n,int flags)
 
   case F_LAND:
   case F_LOR:
-    if(do_docode(CAR(n),0)!=1)
-      fatal("Compiler internal error.\n");
-    tmp1=do_jump(n->token,-1);
-    if(do_docode(CDR(n),0)!=1)
-      fatal("Compiler internal error.\n");
+    tmp1=alloc_label();
+    do_cond_jump(CAR(n), tmp1, n->token == F_LOR, 0);
+    if(do_docode(CDR(n),0)!=1) fatal("Compiler internal error.\n");
     emit(F_LABEL,tmp1);
     return 1;
 
diff --git a/src/interpret.c b/src/interpret.c
index 81bd795b92274ca3ecc615e95e6c3a5e33bff408..dd2f2b027f91255f41cbf5d60ace62847ad4ae3d 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.30 1997/03/09 09:11:11 hubbe Exp $");
+RCSID("$Id: interpret.c,v 1.31 1997/03/11 03:36:39 hubbe Exp $");
 #include "interpret.h"
 #include "object.h"
 #include "program.h"
@@ -882,7 +882,7 @@ static void eval_instruction(unsigned char *pc)
       break;
 
       CASE(F_EQ_OR);
-      if(is_eq(sp-2,sp-1))
+      if(!is_eq(sp-2,sp-1))
       {
 	pop_n_elems(2);
 	pc+=sizeof(INT32);
@@ -893,6 +893,18 @@ static void eval_instruction(unsigned char *pc)
       }
       break;
 
+      CASE(F_EQ_AND);
+      if(is_eq(sp-2,sp-1))
+      {
+	pop_n_elems(2);
+	pc+=sizeof(INT32);
+      }else{
+	pop_n_elems(2);
+	push_int(0);
+	DOJUMP();
+      }
+      break;
+
       CASE(F_CATCH);
       if(o_catch(pc+sizeof(INT32)))
 	return; /* There was a return inside the evaluated code */
diff --git a/src/interpret.h b/src/interpret.h
index d57a09be959bdfd451609a3ee4956fd18f068765..c9a47e19c18d3db1282aabfcca60ac8d03c31cf8 100644
--- a/src/interpret.h
+++ b/src/interpret.h
@@ -33,6 +33,7 @@ struct frame
 #endif
 
 #define pop_stack() do{ free_svalue(--sp); debug_check_stack(); }while(0)
+
 #define push_program(P) do{ struct program *_=(P); sp->u.program=_; sp++->type=T_PROGRAM; }while(0)
 #define push_int(I) do{ INT32 _=(I); sp->u.integer=_;sp->type=T_INT;sp++->subtype=NUMBER_NUMBER; }while(0)
 #define push_mapping(M) do{ struct mapping *_=(M); sp->u.mapping=_; sp++->type=T_MAPPING; }while(0)
@@ -42,6 +43,14 @@ struct frame
 #define push_object(O) do{ struct object  *_=(O); sp->u.object=_; sp++->type=T_OBJECT; }while(0)
 #define push_float(F) do{ float _=(F); sp->u.float_number=_; sp++->type=T_FLOAT; }while(0)
 #define push_text(T) push_string(make_shared_string((T)))
+
+#define ref_push_program(P) do{ struct program *_=(P); _->refs++; sp->u.program=_; sp++->type=T_PROGRAM; }while(0)
+#define ref_push_mapping(M) do{ struct mapping *_=(M); _->refs++; sp->u.mapping=_; sp++->type=T_MAPPING; }while(0)
+#define ref_push_array(A) do{ struct array *_=(A); _->refs++; sp->u.array=_ ;sp++->type=T_ARRAY; }while(0)
+#define ref_push_multiset(L) do{ struct multiset *_=(L); _->refs++; sp->u.multiset=_; sp++->type=T_MULTISET; }while(0)
+#define ref_push_string(S) do{ struct pike_string *_=(S); _->refs++; sp->subtype=0; sp->u.string=_; sp++->type=T_STRING; }while(0)
+#define ref_push_object(O) do{ struct object  *_=(O); _->refs++; sp->u.object=_; sp++->type=T_OBJECT; }while(0)
+
 #define push_svalue(S) do { struct svalue *_=(S); assign_svalue_no_free(sp,_); sp++; }while(0)
 
 #define APPLY_MASTER(FUN,ARGS) \
diff --git a/src/language.yacc b/src/language.yacc
index 5122e1f040d97973c37461a265279cf1f300b3a3..cfa95af187e43da089eafbc37b6f642cb569286f 100644
--- a/src/language.yacc
+++ b/src/language.yacc
@@ -56,7 +56,7 @@
 %token F_AND F_OR F_XOR
 %token F_LSH F_RSH
 %token F_LAND F_LOR
-%token F_EQ_OR
+%token F_EQ_OR F_EQ_AND
 
 %token F_SWITCH F_SSCANF F_CATCH
 %token F_CAST
@@ -158,7 +158,7 @@
 /* This is the grammar definition of Pike. */
 
 #include "global.h"
-RCSID("$Id: language.yacc,v 1.29 1997/03/09 09:11:11 hubbe Exp $");
+RCSID("$Id: language.yacc,v 1.30 1997/03/11 03:36:40 hubbe Exp $");
 #ifdef HAVE_MEMORY_H
 #include <memory.h>
 #endif
diff --git a/src/lex.c b/src/lex.c
index d69d0a1695d719119cc6fc998cf38f93d2552600..248d9dc15f4fbb6774950bdc1abd7bf431c6a9d7 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.17 1997/03/09 09:11:12 hubbe Exp $");
+RCSID("$Id: lex.c,v 1.18 1997/03/11 03:36:41 hubbe Exp $");
 #include "language.h"
 #include "array.h"
 #include "lex.h"
@@ -144,21 +144,16 @@ struct keyword instr_names[]=
 { "!=",			F_NE },	
 { "%",			F_MOD },	
 { "%=",			F_MOD_EQ },	
-{ "& global",           F_GLOBAL_LVALUE, 1 },
-{ "& local",            F_LOCAL_LVALUE, 1 },
+{ "& global",           F_GLOBAL_LVALUE, I_HASARG },
+{ "& local",            F_LOCAL_LVALUE, I_HASARG },
 { "&",			F_AND },
-{ "&&",			F_LAND, 1 },	
 { "&=",			F_AND_EQ },	
 { "*",			F_MULTIPLY },	
 { "*=",			F_MULT_EQ },	
 { "+",			F_ADD },	
-{ "++Loop",		F_INC_LOOP, 1 },	
-{ "++Loop!=",		F_INC_NEQ_LOOP, 1 },
 { "++x",		F_INC },	
 { "+=",			F_ADD_EQ },	
 { "-",			F_SUBTRACT },	
-{ "--Loop",		F_DEC_LOOP, 1 },	
-{ "--Loop!=",		F_DEC_NEQ_LOOP, 1 },
 { "--x",		F_DEC },	
 { "-=",			F_SUB_EQ },	
 { "/",			F_DIVIDE },	
@@ -183,19 +178,16 @@ struct keyword instr_names[]=
 { "arg+=512",		F_PREFIX_512 },
 { "arg+=768",		F_PREFIX_768 },
 { "assign and pop",	F_ASSIGN_AND_POP },
-{ "assign global",	F_ASSIGN_GLOBAL, 1 },
-{ "assign global and pop",	F_ASSIGN_GLOBAL_AND_POP, 1 },
-{ "assign local",       F_ASSIGN_LOCAL, 1 },
-{ "assign local and pop",	F_ASSIGN_LOCAL_AND_POP, 1 },
+{ "assign global",	F_ASSIGN_GLOBAL, I_HASARG },
+{ "assign global and pop",	F_ASSIGN_GLOBAL_AND_POP, I_HASARG },
+{ "assign local",       F_ASSIGN_LOCAL, I_HASARG },
+{ "assign local and pop",	F_ASSIGN_LOCAL_AND_POP, I_HASARG },
 { "assign",		F_ASSIGN },
-{ "branch non zero",	F_BRANCH_WHEN_NON_ZERO, 1 },	
-{ "branch when zero",	F_BRANCH_WHEN_ZERO, 1 },	
 { "break",		F_BREAK },	
 { "case",		F_CASE },	
 { "cast",		F_CAST },	
-{ "catch",		F_CATCH, 1 },
 { "const-1",		F_CONST_1 },	
-{ "constant",           F_CONSTANT, 1 },
+{ "constant",           F_CONSTANT, I_HASARG },
 { "continue",		F_CONTINUE },	
 { "copy_value",         F_COPY_VALUE },
 { "default",		F_DEFAULT },	
@@ -203,37 +195,57 @@ struct keyword instr_names[]=
 { "dumb return",	F_DUMB_RETURN },	
 { "float number",	F_FLOAT },
 { "for",		F_FOR },
-{ "foreach",		F_FOREACH, 1 },
-{ "global",		F_GLOBAL, 1 },
+{ "global",		F_GLOBAL, I_HASARG },
 { "index",              F_INDEX },
-{ "->",                 F_ARROW, 1 },
+{ "->",                 F_ARROW, I_HASARG },
 { "clear string subtype", F_CLEAR_STRING_SUBTYPE },
-{ "arrow string",       F_ARROW_STRING, 1 },
+{ "arrow string",       F_ARROW_STRING, I_HASARG },
 { "indirect",		F_INDIRECT },
-{ "jump",               F_BRANCH, 1 },
-{ "local function call",F_CALL_LFUN, 1 },
-{ "local function call and pop",F_CALL_LFUN_AND_POP, 1 },
-{ "local function",	F_LFUN, 1 },	
-{ "local",		F_LOCAL, 1 },	
-{ "mark & local",	F_MARK_AND_LOCAL, 1 },	
+
+{ "branch",             F_BRANCH, I_ISJUMP },
+{ "branch non zero",	F_BRANCH_WHEN_NON_ZERO, I_ISJUMP },	
+{ "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 },
+{ "branch if <=",	F_BRANCH_WHEN_LE, I_ISJUMP },
+{ "branch if >=",	F_BRANCH_WHEN_GE, I_ISJUMP },
+{ "branch if ==",	F_BRANCH_WHEN_EQ, I_ISJUMP },
+{ "branch if !=",	F_BRANCH_WHEN_NE, I_ISJUMP },
+{ "++Loop",		F_INC_LOOP, I_ISJUMP },	
+{ "++Loop!=",		F_INC_NEQ_LOOP, I_ISJUMP },
+{ "--Loop",		F_DEC_LOOP, I_ISJUMP },	
+{ "--Loop!=",		F_DEC_NEQ_LOOP, I_ISJUMP },
+{ "&&",			F_LAND, I_ISJUMP },	
+{ "||",			F_LOR, I_ISJUMP },	
+{ "==||",               F_EQ_OR, I_ISJUMP },
+{ "==&&",               F_EQ_AND, I_ISJUMP },
+{ "catch",		F_CATCH, I_ISJUMP },
+{ "foreach",		F_FOREACH, I_ISJUMP },
+{ "data",		F_POINTER, I_ISPOINTER },
+
+{ "local function call",F_CALL_LFUN, I_HASARG },
+{ "local function call and pop",F_CALL_LFUN_AND_POP, I_HASARG },
+{ "local function",	F_LFUN, I_HASARG },	
+{ "local",		F_LOCAL, I_HASARG },	
+{ "mark & local",	F_MARK_AND_LOCAL, I_HASARG },	
 { "ltosval2",		F_LTOSVAL2 },
 { "lvalue to svalue",	F_LTOSVAL },	
 { "lvalue_list",	F_LVALUE_LIST },	
 { "mark",               F_MARK },
 { "mark mark",          F_MARK2 },
-{ "negative number",	F_NEG_NUMBER, 1 },
-{ "number",             F_NUMBER, 1 },
+{ "negative number",	F_NEG_NUMBER, I_HASARG },
+{ "number",             F_NUMBER, I_HASARG },
 { "pop",		F_POP_VALUE },	
-{ "pop_n_elems",        F_POP_N_ELEMS, 1 },
+{ "pop_n_elems",        F_POP_N_ELEMS, I_HASARG },
 { "push 0",             F_CONST0 },
 { "push 1",             F_CONST1 },
 { "push 0x7fffffff",    F_BIGNUM },
 { "range",              F_RANGE },
 { "return",		F_RETURN },
 { "return 0",		F_RETURN_0 },
-{ "sscanf",		F_SSCANF, 1 },	
-{ "string",             F_STRING, 1 },
-{ "switch",		F_SWITCH, 1 },
+{ "sscanf",		F_SSCANF, I_HASARG },	
+{ "string",             F_STRING, I_HASARG },
+{ "switch",		F_SWITCH, I_HASARG },
 { "unary minus",	F_NEGATE },
 { "while",		F_WHILE },	
 { "x++ and pop",	F_INC_AND_POP },	
@@ -242,38 +254,29 @@ struct keyword instr_names[]=
 { "x--",		F_POST_DEC },	
 { "|",			F_OR },
 { "|=",			F_OR_EQ },	
-{ "||",			F_LOR, 1 },	
 { "~",			F_COMPL },
 { "label",		F_LABEL,1 },
-{ "data",		F_POINTER, 1 },
-{ "align",		F_ALIGN, 1 },
-{ "call",		F_APPLY, 1 },
-{ "clear local",	F_CLEAR_LOCAL, 1 },
-{ "clear 2 local",	F_CLEAR_2_LOCAL, 1 },
-{ "++local",		F_INC_LOCAL, 1 },
-{ "++local and pop",	F_INC_LOCAL_AND_POP, 1 },
-{ "local++",		F_POST_INC_LOCAL, 1 },
-{ "--local",		F_DEC_LOCAL, 1 },
-{ "--local and pop",	F_DEC_LOCAL_AND_POP, 1 },
-{ "local--",		F_POST_DEC_LOCAL, 1 },
-{ "branch if <",	F_BRANCH_WHEN_LT, 1 },
-{ "branch if >",	F_BRANCH_WHEN_GT, 1 },
-{ "branch if <=",	F_BRANCH_WHEN_LE, 1 },
-{ "branch if >=",	F_BRANCH_WHEN_GE, 1 },
-{ "branch if ==",	F_BRANCH_WHEN_EQ, 1 },
-{ "branch if !=",	F_BRANCH_WHEN_NE, 1 },
+{ "align",		F_ALIGN, I_HASARG },
+{ "call",		F_APPLY, I_HASARG },
+{ "clear local",	F_CLEAR_LOCAL, I_HASARG },
+{ "clear 2 local",	F_CLEAR_2_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 },
+{ "--local",		F_DEC_LOCAL, I_HASARG },
+{ "--local and pop",	F_DEC_LOCAL_AND_POP, I_HASARG },
+{ "local--",		F_POST_DEC_LOCAL, I_HASARG },
 { "sizeof",		F_SIZEOF },
-{ "sizeof local",	F_SIZEOF_LOCAL, 1 },
+{ "sizeof local",	F_SIZEOF_LOCAL, I_HASARG },
 { "throw(0)",		F_THROW_ZERO },
-{ "string index",       F_STRING_INDEX, 1 },
-{ "local index",        F_LOCAL_INDEX, 1 },
-{ "int index",          F_POS_INT_INDEX, 1 },
-{ "-int index",         F_NEG_INT_INDEX, 1 },
-{ "apply and pop",      F_APPLY_AND_POP, 1 },
-{ "2 locals",           F_2_LOCALS, 1 },
-{ "byte",               F_BYTE, 1 },
+{ "string index",       F_STRING_INDEX, I_HASARG },
+{ "local index",        F_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 },
+{ "2 locals",           F_2_LOCALS, I_HASARG },
+{ "byte",               F_BYTE, I_HASARG },
 { "nop",                F_NOP },
-{ "==||",               F_EQ_OR, 1 },
 };
 
 struct instr instrs[F_MAX_INSTR - F_OFFSET];
@@ -298,7 +301,7 @@ void init_lex()
       fatal("Duplicate name for %s\n",instr_names[i].word);
 
     instrs[instr_names[i].token - F_OFFSET].name = instr_names[i].word;
-    instrs[instr_names[i].token - F_OFFSET].hasarg=instr_names[i].hasarg;
+    instrs[instr_names[i].token - F_OFFSET].flags=instr_names[i].flags;
   }
 
   reswords=create_hash_table();
diff --git a/src/lex.h b/src/lex.h
index 381f0786a62c84b5b40033774ab164a21cc4bb37..e5d0f5ba7649e8436dce6e286e7e02d75ee85454 100644
--- a/src/lex.h
+++ b/src/lex.h
@@ -12,16 +12,22 @@ struct keyword
 {
   char *word;
   int token;
-  int hasarg;
+  int flags;
 };
 
+#define I_HASARG 1
+#define I_POINTER 2
+#define I_JUMP 4
+#define I_ISPOINTER 3
+#define I_ISJUMP 7
+
 struct instr
 {
 #ifdef DEBUG
   long runs;
   long compiles;
 #endif
-  int hasarg;
+  int flags;
   char *name;
 };
 
diff --git a/src/peep.c b/src/peep.c
index 9a3124daff9bcfce961d315ef634fb7a95634392..c287b6498373f828b8e801361f7de3ba39d750b4 100644
--- a/src/peep.c
+++ b/src/peep.c
@@ -24,7 +24,10 @@ static void asm_opt(void);
 
 dynamic_buffer instrbuf;
 
-static int hasarg(int opcode) { return instrs[opcode-F_OFFSET].hasarg; }
+static int hasarg(int opcode)
+{
+  return instrs[opcode-F_OFFSET].flags & I_HASARG;
+}
 
 void init_bytecode()
 {
@@ -138,27 +141,6 @@ static void ins_f_byte_with_arg(unsigned int a,unsigned INT32 b)
   ins_byte(b, A_PROGRAM);
 }
 
-#define BRANCH_CASES \
-         F_BRANCH_WHEN_EQ: \
-    case F_BRANCH_WHEN_NE: \
-    case F_BRANCH_WHEN_LT: \
-    case F_BRANCH_WHEN_LE: \
-    case F_BRANCH_WHEN_GT: \
-    case F_BRANCH_WHEN_GE: \
-    case F_BRANCH_WHEN_ZERO: \
-    case F_BRANCH_WHEN_NON_ZERO: \
-    case F_BRANCH: \
-    case F_INC_LOOP: \
-    case F_DEC_LOOP: \
-    case F_INC_NEQ_LOOP: \
-    case F_DEC_NEQ_LOOP: \
-    case F_LAND: \
-    case F_LOR: \
-    case F_EQ_OR: \
-    case F_CATCH: \
-    case F_FOREACH
-
-
 void assemble(void)
 {
   INT32 e,d,length,max_label,tmp;
@@ -193,10 +175,8 @@ void assemble(void)
 
   for(e=0;e<length;e++)
   {
-    switch(c[e].opcode)
+    if(instrs[c[e].opcode-F_OFFSET].flags & I_POINTER)
     {
-    case BRANCH_CASES:
-    case F_POINTER:
       while(1)
       {
 	int tmp,tmp2;
@@ -282,24 +262,33 @@ void assemble(void)
       labels[c->arg]=PC;
       break;
 
-    case BRANCH_CASES:
-      ins_f_byte(c->opcode);
-
-    case F_POINTER:
+    default:
+      switch(instrs[c->opcode - F_OFFSET].flags)
+      {
+      case I_ISJUMP:
+	ins_f_byte(c->opcode);
+      case I_ISPOINTER:
 #ifdef DEBUG
-      if(c->arg > max_label || c->arg < 0) fatal("Jump to unknown label?\n");
+	if(c->arg > max_label || c->arg < 0) fatal("Jump to unknown label?\n");
 #endif
-      tmp=PC;
-      ins_int(jumps[c->arg],A_PROGRAM);
-      jumps[c->arg]=tmp;
-      break;
+	tmp=PC;
+	ins_int(jumps[c->arg],A_PROGRAM);
+	jumps[c->arg]=tmp;
+	break;
 
-    default:
-      if(hasarg(c->opcode))
+      case I_HASARG:
 	ins_f_byte_with_arg(c->opcode, c->arg);
-      else
+	break;
+
+      case 0:
 	ins_f_byte(c->opcode);
-      break;
+	break;
+
+#ifdef DEBUG
+      default:
+	fatal("Unknown instruction type.\n");
+#endif
+      }
     }
     
     c++;
diff --git a/src/peep.in b/src/peep.in
index 3fab269e3d2ab8c1d046d72ec376ad533bdde213..49481badcf9ce7e4030f8cbc0366708c2889ecec 100644
--- a/src/peep.in
+++ b/src/peep.in
@@ -95,6 +95,7 @@ LE BRANCH_WHEN_ZERO: BRANCH_WHEN_GT ($2a)
 GE BRANCH_WHEN_ZERO: BRANCH_WHEN_LT ($2a)
 
 EQ LOR: EQ_OR ($2a)
+EQ LAND: EQ_AND ($2a)
 
 EQ NOT: NE
 NE NOT: EQ
diff --git a/src/program.c b/src/program.c
index fb7b81f151532f0551267bd7bc06a8413c33e179..f9984d738676b8f3fd0489a4860bc0da3343bb10 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.25 1997/03/07 05:21:47 hubbe Exp $");
+RCSID("$Id: program.c,v 1.26 1997/03/11 03:36:42 hubbe Exp $");
 #include "program.h"
 #include "object.h"
 #include "dynamic_buffer.h"
@@ -966,6 +966,8 @@ int add_constant(struct pike_string *name,
 		 INT32 flags)
 {
   int n;
+  struct identifier dummy;
+  struct reference ref;
 
 #ifdef DEBUG
   if(name!=debug_findstring(name))
@@ -975,38 +977,34 @@ int add_constant(struct pike_string *name,
   setup_fake_program();
   n = isidentifier(name);
 
+  copy_shared_string(dummy.name, name);
+  dummy.type = get_type_of_svalue(c);
+  
+  dummy.flags = IDENTIFIER_CONSTANT;
+  dummy.run_time_type=c->type;
+  
+  dummy.func.offset=store_constant(c, 0);
+
+  ref.flags=flags;
+  ref.identifier_offset=fake_program.num_identifiers;
+  ref.inherit_offset=0;
+
+  add_to_mem_block(A_IDENTIFIERS, (char *)&dummy, sizeof dummy);
+  fake_program.num_identifiers ++;
+
   if(n != -1)
   {
-    setup_fake_program();
-
     if (IDENTIFIERP(n)->flags & ID_NOMASK)
       my_yyerror("Illegal to redefine 'nomask' identifier \"%s\"", name->str);
 
     if(PROG_FROM_INT(& fake_program, n) == &fake_program)
       my_yyerror("Identifier '%s' defined twice.",name->str);
-  } else {
-    struct identifier dummy;
-    struct reference ref;
-
-    copy_shared_string(dummy.name, name);
-    dummy.type = get_type_of_svalue(c);
-    
-    dummy.flags = IDENTIFIER_CONSTANT;
-    dummy.run_time_type=c->type;
-    
-    dummy.func.offset=store_constant(c, 0);
-
-    ref.flags=flags;
-    ref.identifier_offset=areas[A_IDENTIFIERS].s.len / sizeof dummy;
-    ref.inherit_offset=0;
-
-    add_to_mem_block(A_IDENTIFIERS, (char *)&dummy, sizeof dummy);
-    fake_program.num_identifiers ++;
 
+    fake_program.identifier_references[n]=ref;
+  } else {
     n=areas[A_IDENTIFIER_REFERENCES].s.len / sizeof ref;
     add_to_mem_block(A_IDENTIFIER_REFERENCES, (char *)&ref, sizeof ref);
     fake_program.num_identifier_references ++;
-
   }
 
   return n;
diff --git a/src/testsuite.in b/src/testsuite.in
index ccc03668444df682352d9116bfe6ac19edb04987..b860ea9a346e4f34ada0f07deef9db39e331ea1f 100644
--- a/src/testsuite.in
+++ b/src/testsuite.in
@@ -1,4 +1,5 @@
-test_true([["$Id: testsuite.in,v 1.34 1997/03/09 09:11:13 hubbe Exp $"]])
+test_true([["$Id: testsuite.in,v 1.35 1997/03/11 03:36:42 hubbe Exp $"]])
+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"); }]])
 test_true([[lambda(function f) {return 1;}(object_program(this_object()));]])
 test_eq([[class { int `()(){ return 4711; } }()(); ]],4711)