diff --git a/src/builtin_functions.c b/src/builtin_functions.c
index 4492d936c0c2d387df6b539300b2c0953d75e4c6..0b28901cf95a3f8e8b693d860703856bc6437fe4 100644
--- a/src/builtin_functions.c
+++ b/src/builtin_functions.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: builtin_functions.c,v 1.75 1998/02/27 19:22:34 hubbe Exp $");
+RCSID("$Id: builtin_functions.c,v 1.76 1998/03/01 11:40:46 hubbe Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "pike_macros.h"
@@ -2383,18 +2383,18 @@ void init_builtin_efuns(void)
   add_efun("replace_master",f_replace_master,"function(object:void)",OPT_SIDE_EFFECT);
   add_efun("master",f_master,"function(:object)",OPT_EXTERNAL_DEPEND);
   add_efun("add_constant",f_add_constant,"function(string,void|mixed:void)",OPT_SIDE_EFFECT);
-  add_efun("aggregate",f_aggregate,"function(mixed ...:mixed *)",OPT_TRY_OPTIMIZE);
-  add_efun("aggregate_multiset",f_aggregate_multiset,"function(mixed ...:multiset)",OPT_TRY_OPTIMIZE);
-  add_efun("aggregate_mapping",f_aggregate_mapping,"function(mixed ...:mapping)",OPT_TRY_OPTIMIZE);
+  add_efun("aggregate",f_aggregate,"function(0=mixed ...:array(0))",OPT_TRY_OPTIMIZE);
+  add_efun("aggregate_multiset",f_aggregate_multiset,"function(0=mixed ...:multiset(0))",OPT_TRY_OPTIMIZE);
+  add_efun("aggregate_mapping",f_aggregate_mapping,"function(0=mixed ...:mapping(0:0))",OPT_TRY_OPTIMIZE);
   add_efun("all_constants",f_all_constants,"function(:mapping(string:mixed))",OPT_EXTERNAL_DEPEND);
-  add_efun("allocate", f_allocate, "function(int, mixed:mixed *)", 0);
+  add_efun("allocate", f_allocate, "function(int,void|mixed:array)", 0);
   add_efun("arrayp",  f_arrayp,  "function(mixed:int)",0);
   add_efun("backtrace",f_backtrace,"function(:array(array(function|int|string)))",OPT_EXTERNAL_DEPEND);
 
   add_efun("column",f_column,"function(array,mixed:array)",0);
   add_efun("combine_path",f_combine_path,"function(string,string:string)",0);
   add_efun("compile",f_compile,"function(string:program)",OPT_EXTERNAL_DEPEND);
-  add_efun("copy_value",f_copy_value,"function(mixed:mixed)",0);
+  add_efun("copy_value",f_copy_value,"function(1=mixed:1)",0);
   add_efun("crypt",f_crypt,"function(string:string)|function(string,string:int)",OPT_EXTERNAL_DEPEND);
   add_efun("ctime",f_ctime,"function(int:string)",OPT_TRY_OPTIMIZE);
   add_efun("destruct",f_destruct,"function(object|void:void)",OPT_SIDE_EFFECT);
@@ -2406,13 +2406,13 @@ void init_builtin_efuns(void)
   add_efun("functionp",  f_functionp,  "function(mixed:int)",OPT_TRY_OPTIMIZE);
   add_efun("glob",f_glob,"function(string,string:int)|function(string,string*:array(string))",OPT_TRY_OPTIMIZE);
   add_efun("hash",f_hash,"function(string,int|void:int)",OPT_TRY_OPTIMIZE);
-  add_efun("indices",f_indices,"function(string|array:int*)|function(mapping|multiset:mixed*)|function(object:string*)",0);
+  add_efun("indices",f_indices,"function(string|array:int*)|function(mapping(1=mixed:mixed)|multiset(1=mixed):array(1))|function(object:string*)",0);
   add_efun("intp",   f_intp,    "function(mixed:int)",OPT_TRY_OPTIMIZE);
   add_efun("multisetp",   f_multisetp,   "function(mixed:int)",OPT_TRY_OPTIMIZE);
   add_efun("lower_case",f_lower_case,"function(string:string)",OPT_TRY_OPTIMIZE);
-  add_efun("m_delete",f_m_delete,"function(mapping,mixed:mapping)",0);
+  add_efun("m_delete",f_m_delete,"function(0=mapping,mixed:0)",0);
   add_efun("mappingp",f_mappingp,"function(mixed:int)",OPT_TRY_OPTIMIZE);
-  add_efun("mkmapping",f_mkmapping,"function(mixed *,mixed *:mapping)",OPT_TRY_OPTIMIZE);
+  add_efun("mkmapping",f_mkmapping,"function(array(1=mixed),array(2=mixed):mapping(1:2))",OPT_TRY_OPTIMIZE);
   add_efun("next_object",f_next_object,"function(void|object:object)",OPT_EXTERNAL_DEPEND);
   add_efun("_next",f__next,"function(string:string)|function(object:object)|function(mapping:mapping)|function(multiset:multiset)|function(program:program)|function(array:array)",OPT_EXTERNAL_DEPEND);
   add_efun("_prev",f__prev,"function(object:object)|function(mapping:mapping)|function(multiset:multiset)|function(program:program)|function(array:array)",OPT_EXTERNAL_DEPEND);
@@ -2422,20 +2422,20 @@ void init_builtin_efuns(void)
   add_efun("query_num_arg",f_query_num_arg,"function(:int)",OPT_EXTERNAL_DEPEND);
   add_efun("random",f_random,"function(int:int)",OPT_EXTERNAL_DEPEND);
   add_efun("random_seed",f_random_seed,"function(int:void)",OPT_SIDE_EFFECT);
-  add_efun("replace",f_replace,"function(string,string,string:string)|function(string,string*,string*:string)|function(array,mixed,mixed:array)|function(mapping,mixed,mixed:array)",0);
+  add_efun("replace",f_replace,"function(string,string,string:string)|function(string,string*,string*:string)|function(0=array,mixed,mixed:0)|function(1=mapping,mixed,mixed:1)",0);
   add_efun("reverse",f_reverse,"function(int:int)|function(string:string)|function(array:array)",0);
   add_efun("rows",f_rows,"function(mixed,array:array)",0);
   add_efun("rusage", f_rusage, "function(:int *)",OPT_EXTERNAL_DEPEND);
   add_efun("search",f_search,"function(string,string,void|int:int)|function(array,mixed,void|int:int)|function(mapping,mixed:mixed)",0);
   add_efun("sleep", f_sleep, "function(float|int:void)",OPT_SIDE_EFFECT);
-  add_efun("sort",f_sort,"function(array(mixed),array(mixed)...:array(mixed))",OPT_SIDE_EFFECT);
+  add_efun("sort",f_sort,"function(array(0=mixed),array(mixed)...:array(0))",OPT_SIDE_EFFECT);
   add_efun("stringp", f_stringp, "function(mixed:int)",0);
   add_efun("this_object", f_this_object, "function(:object)",OPT_EXTERNAL_DEPEND);
   add_efun("throw",f_throw,"function(mixed:void)",OPT_SIDE_EFFECT);
   add_efun("time",f_time,"function(void|int:int)",OPT_EXTERNAL_DEPEND);
   add_efun("trace",f_trace,"function(int:int)",OPT_SIDE_EFFECT);
   add_efun("upper_case",f_upper_case,"function(string:string)",0);
-  add_efun("values",f_values,"function(string|multiset:int*)|function(array|mapping|object:mixed*)",0);
+  add_efun("values",f_values,"function(string|multiset:int*)|function(array(0=mixed)|mapping(mixed:0=mixed)|object:array(0))",0);
   add_efun("zero_type",f_zero_type,"function(mixed:int)",0);
 
 #ifdef HAVE_LOCALTIME
diff --git a/src/docode.c b/src/docode.c
index 55d3fd176c2e2714e2dc7235b587ba1c6bb80a41..fb882687a0cfcb94d9f0996a3b35211ccf3147da 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.32 1998/02/27 18:16:44 hubbe Exp $");
+RCSID("$Id: docode.c,v 1.33 1998/03/01 11:40:46 hubbe Exp $");
 #include "las.h"
 #include "program.h"
 #include "language.h"
@@ -671,7 +671,7 @@ static int do_docode2(node *n,int flags)
 	  if(n->type == void_type_string) return 0;
 	  return 1;
 	}else{
-	  if(CAR(n)->u.sval.u.object->next == fake_object)
+	  if(CAR(n)->u.sval.u.object == fake_object)
 	  {
 	    emit2(F_MARK);
 	    do_docode(CDR(n),0);
diff --git a/src/las.c b/src/las.c
index 2fcbbb9f26fa31ea277e0a2fcaeff075cedb0224..33a21343d4dda92f174c2349c2524187d29ba628 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.54 1998/03/01 03:39:37 hubbe Exp $");
+RCSID("$Id: las.c,v 1.55 1998/03/01 11:40:46 hubbe Exp $");
 
 #include "language.h"
 #include "interpret.h"
@@ -393,6 +393,11 @@ node *mknode(short token,node *a,node *b)
   if(a) a->parent = res;
   if(b) b->parent = res;
 
+#ifdef DEBUG
+  if(d_flag > 3)
+    verify_shared_strings_tables();
+#endif
+
   if(!num_parse_error && compiler_pass==2)
   {
     check_tree(res,0);
diff --git a/src/operators.c b/src/operators.c
index 14751029106a67efd190f48e65866a7531d8930e..4ebd95d562e08ab0baea873a3ddeb063179633e4 100644
--- a/src/operators.c
+++ b/src/operators.c
@@ -5,7 +5,7 @@
 \*/
 #include <math.h>
 #include "global.h"
-RCSID("$Id: operators.c,v 1.27 1998/02/27 19:20:11 hubbe Exp $");
+RCSID("$Id: operators.c,v 1.28 1998/03/01 11:40:46 hubbe Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "multiset.h"
@@ -1748,7 +1748,15 @@ void init_operators(void)
   add_efun2("`>", f_gt,CMP_TYPE,OPT_TRY_OPTIMIZE,0,generate_comparison);
   add_efun2("`>=",f_ge,CMP_TYPE,OPT_TRY_OPTIMIZE,0,generate_comparison);
 
-  add_efun2("`+",f_add,"!function(!object...:mixed)&function(mixed...:mixed)|function(int...:int)|!function(int...:mixed)&function(int|float...:float)|!function(int|float...:mixed)&function(string|int|float...:string)|function(array...:array)|function(mapping...:mapping)|function(multiset...:multiset)",OPT_TRY_OPTIMIZE,optimize_binary,generate_sum);
+  add_efun2("`+",f_add,
+	    "!function(!object...:mixed)&function(mixed...:mixed)|"
+	    "function(int...:int)|"
+	    "!function(int...:mixed)&function(int|float...:float)|"
+	    "!function(int|float...:mixed)&function(string|int|float...:string)|"
+	    "function(0=array...:0)|"
+	    "function(mapping(1=mixed:2=mixed)...:mapping(1:2))|"
+	    "function(3=multiset...:3)",
+	    OPT_TRY_OPTIMIZE,optimize_binary,generate_sum);
 
   add_efun2("`-",f_minus,"!function(!object...:mixed)&function(mixed...:mixed)|function(int:int)|function(float:float)|function(array,array:array)|function(mapping,mapping:mapping)|function(multiset,multiset:multiset)|function(float|int,float:float)|function(float,int:float)|function(int,int:int)|function(string,string:string)",OPT_TRY_OPTIMIZE,0,generate_minus);
 
@@ -1768,11 +1776,11 @@ void init_operators(void)
 
   add_efun2("`*",f_multiply,
 	    "!function(!object...:mixed)&function(mixed...:mixed)|"
-	    "function(array(array),array:array)|"
+	    "function(array(1=array),1=array:1)|"
 	    "function(int...:int)|"
 	    "!function(int...:mixed)&function(float|int...:float)|"
 	    "function(string*,string:string)|"
-	    "function(array,int:array)|"
+	    "function(0=array,int:0)|"
 	    "function(string,int:string)",
 	    OPT_TRY_OPTIMIZE,optimize_binary,generate_multiply);
 
@@ -1780,7 +1788,7 @@ void init_operators(void)
 	    "!function(!object...:mixed)&function(mixed...:mixed)|"
 	    "function(int,int...:int)|"
 	    "!function(int...:mixed)&function(float|int...:float)|"
-	    "function(array,array|int|float...:array(array))|"
+	    "function(0=array,array|int|float...:array(0))|"
 	    "function(string,string|int|float...:array(string))",
 	    OPT_TRY_OPTIMIZE,0,generate_divide);
 
@@ -1789,7 +1797,7 @@ void init_operators(void)
 	    "function(object,mixed:mixed)|"
 	    "function(int,int:int)|"
 	    "function(string,int:string)|"
-	    "function(array,int:array)|"
+	    "function(0=array,int:0)|"
 	    "!function(int,int:mixed)&function(int|float,int|float:float)"
 	    ,OPT_TRY_OPTIMIZE,0,generate_mod);
 
diff --git a/src/pike_types.c b/src/pike_types.c
index a76cc29f1beb00b48fe03cf196ac3e05c41de47e..287148ef401f8b88ad1e6d251aa12036b843b099 100644
--- a/src/pike_types.c
+++ b/src/pike_types.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: pike_types.c,v 1.33 1998/02/24 23:01:31 hubbe Exp $");
+RCSID("$Id: pike_types.c,v 1.34 1998/03/01 11:40:47 hubbe Exp $");
 #include <ctype.h>
 #include "svalue.h"
 #include "pike_types.h"
@@ -61,6 +61,14 @@ struct pike_string *mixed_type_string;
 struct pike_string *void_type_string;
 struct pike_string *any_type_string;
 
+static char *a_markers[10],*b_markers[10];
+
+static void clear_markers()
+{
+  unsigned int e;
+  for(e=0;e<NELEM(a_markers);e++) a_markers[e]=b_markers[e]=0;
+}
+
 #ifdef DEBUG
 static void CHECK_TYPE(struct pike_string *s)
 {
@@ -68,7 +76,10 @@ static void CHECK_TYPE(struct pike_string *s)
     fatal("Type string not shared.\n");
 
   if(type_length(s->str) != s->len)
+  {
+    stupid_describe_type(s->str,s->len);
     fatal("Length of type is wrong.\n");
+  }
 }
 #else
 #define CHECK_TYPE(X)
@@ -96,36 +107,53 @@ static int type_length(char *t)
 
   switch(EXTRACT_UCHAR(t++))
   {
-  default:
-    fatal("error in type string.\n");
-    /*NOTREACHED*/
-
-  case T_FUNCTION:
-    while(EXTRACT_UCHAR(t)!=T_MANY) t+=type_length(t); /* skip arguments */
-    t++;
-
-  case T_MAPPING:
-  case T_OR:
-  case T_AND:
-    t+=type_length(t);
-
-  case T_ARRAY:
-  case T_MULTISET:
-  case T_NOT:
-    t+=type_length(t);
-
-  case T_INT:
-  case T_FLOAT:
-  case T_STRING:
-  case T_PROGRAM:
-  case T_MIXED:
-  case T_VOID:
-  case T_UNKNOWN:
-    break;
-
-  case T_OBJECT:
-    t+=sizeof(INT32);
-    break;
+    default:
+      fatal("error in type string.\n");
+      /*NOTREACHED*/
+      
+      break;
+      
+    case T_ASSIGN:
+      t++;
+      t+=type_length(t);
+      break;
+      
+    case T_FUNCTION:
+      while(EXTRACT_UCHAR(t)!=T_MANY) t+=type_length(t); /* skip arguments */
+      t++;
+      
+    case T_MAPPING:
+    case T_OR:
+    case T_AND:
+      t+=type_length(t);
+      
+    case T_ARRAY:
+    case T_MULTISET:
+    case T_NOT:
+      t+=type_length(t);
+      
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+    case T_INT:
+    case T_FLOAT:
+    case T_STRING:
+    case T_PROGRAM:
+    case T_MIXED:
+    case T_VOID:
+    case T_UNKNOWN:
+      break;
+      
+    case T_OBJECT:
+      t+=sizeof(INT32);
+      break;
   }
   return t-q;
 }
@@ -205,6 +233,26 @@ void push_unfinished_type(char *s)
   for(e--;e>=0;e--) push_type(s[e]);
 }
 
+static void push_unfinished_type_with_markers(char *s, char **am)
+{
+  int e;
+  e=type_length(s);
+  for(e--;e>=0;e--)
+  {
+    if(s[e]>='0' && s[e]<='9')
+    {
+      if(am[s[e]-'0'])
+      {
+	push_unfinished_type(am[s[e]-'0']);
+      }else{
+	push_type(T_MIXED);
+      }
+    }else{
+      push_type(s[e]);
+    }
+  }
+}
+
 void push_finished_type(struct pike_string *type)
 {
   int e;
@@ -369,6 +417,19 @@ static void internal_parse_typeA(char **_s)
     }
     push_type(T_MULTISET);
   }
+  else if(buf[0]>='0' && buf[0]<='9' && atoi(buf)<10)
+  {
+    while(ISSPACE(**s)) ++*s;
+    if(**s=='=')
+    {
+      ++*s;
+      internal_parse_type(_s);
+      push_type(buf[0]);
+      push_type(T_ASSIGN);
+    }else{
+      push_type(buf[0]);
+    }
+  }
   else
     error("Couldn't parse type. (%s)\n",buf);
 
@@ -476,28 +537,34 @@ void stupid_describe_type(char *a,INT32 len)
     if(e) printf(" ");
     switch(EXTRACT_UCHAR(a+e))
     {
-    case T_INT: printf("int"); break;
-    case T_FLOAT: printf("float"); break;
-    case T_STRING: printf("string"); break;
-    case T_PROGRAM: printf("program"); break;
-    case T_OBJECT:
-      printf("object(%ld)",(long)EXTRACT_INT(a+e+1));
-      e+=sizeof(INT32);
-      break;
-    case T_FUNCTION: printf("function"); break;
-    case T_ARRAY: printf("array"); break;
-    case T_MAPPING: printf("mapping"); break;
-    case T_MULTISET: printf("multiset"); break;
-
-    case T_UNKNOWN: printf("unknown"); break;
-    case T_MANY: printf("many"); break;
-    case T_OR: printf("or"); break;
-    case T_AND: printf("and"); break;
-    case T_NOT: printf("not"); break;
-    case T_VOID: printf("void"); break;
-    case T_MIXED: printf("mixed"); break;
-
-    default: printf("%d",EXTRACT_UCHAR(a+e)); break;
+      case '0': case '1': case '2': case '3': case '4':
+      case '5': case '6': case '7': case '8': case '9':
+	printf("%c",EXTRACT_UCHAR(a+e));
+	break;
+	
+      case T_ASSIGN: printf("="); break;
+      case T_INT: printf("int"); break;
+      case T_FLOAT: printf("float"); break;
+      case T_STRING: printf("string"); break;
+      case T_PROGRAM: printf("program"); break;
+      case T_OBJECT:
+	printf("object(%ld)",(long)EXTRACT_INT(a+e+1));
+	e+=sizeof(INT32);
+	break;
+      case T_FUNCTION: printf("function"); break;
+      case T_ARRAY: printf("array"); break;
+      case T_MAPPING: printf("mapping"); break;
+      case T_MULTISET: printf("multiset"); break;
+	
+      case T_UNKNOWN: printf("unknown"); break;
+      case T_MANY: printf("many"); break;
+      case T_OR: printf("or"); break;
+      case T_AND: printf("and"); break;
+      case T_NOT: printf("not"); break;
+      case T_VOID: printf("void"); break;
+      case T_MIXED: printf("mixed"); break;
+	
+      default: printf("%d",EXTRACT_UCHAR(a+e)); break;
     }
   }
   printf("\n");
@@ -513,92 +580,105 @@ char *low_describe_type(char *t)
 {
   switch(EXTRACT_UCHAR(t++))
   {
-  case T_VOID: my_strcat("void"); break;
-  case T_MIXED: my_strcat("mixed"); break;
-  case T_UNKNOWN: my_strcat("unknown"); break;
-  case T_INT: my_strcat("int"); break;
-  case T_FLOAT: my_strcat("float"); break;
-  case T_PROGRAM: my_strcat("program"); break;
-  case T_OBJECT:
-    my_strcat("object");
-    t+=4;
-    /* Prog id */
-    break;
-  case T_STRING: my_strcat("string"); break;
-
-  case T_FUNCTION:
-  {
-    int s;
-    my_strcat("function(");
-    s=0;
-    while(EXTRACT_UCHAR(t) != T_MANY)
-    {
-      if(s++) my_strcat(", ");
-      t=low_describe_type(t);
-    }
-    t++;
-    if(EXTRACT_UCHAR(t) == T_VOID)
-    {
-      t++;
-    }else{
-      if(s++) my_strcat(", ");
+    case '0': case '1': case '2': case '3': case '4':
+    case '5': case '6': case '7': case '8': case '9':
+      my_putchar(EXTRACT_UCHAR(t-1));
+      break;
+      
+    case T_ASSIGN:
+      my_putchar('(');
+      my_putchar(EXTRACT_UCHAR(t++));
+      my_putchar('=');
       t=low_describe_type(t);
-      my_strcat(" ...");
-    }
-    my_strcat(" : ");
-    t=low_describe_type(t);
-    my_strcat(")");
-    break;
-  }
-
-  case T_ARRAY:
-    if(EXTRACT_UCHAR(t)==T_MIXED)
+      my_putchar(')');
+      break;
+      
+    case T_VOID: my_strcat("void"); break;
+    case T_MIXED: my_strcat("mixed"); break;
+    case T_UNKNOWN: my_strcat("unknown"); break;
+    case T_INT: my_strcat("int"); break;
+    case T_FLOAT: my_strcat("float"); break;
+    case T_PROGRAM: my_strcat("program"); break;
+    case T_OBJECT:
+      my_strcat("object");
+      t+=4;
+      /* Prog id */
+      break;
+    case T_STRING: my_strcat("string"); break;
+      
+    case T_FUNCTION:
     {
-      my_strcat("array");
+      int s;
+      my_strcat("function(");
+      s=0;
+      while(EXTRACT_UCHAR(t) != T_MANY)
+      {
+	if(s++) my_strcat(", ");
+	t=low_describe_type(t);
+      }
       t++;
-    }else{
-      t=low_describe_type(t);
-      my_strcat("*");
-    }
-    break;
-
-  case T_MULTISET:
-    my_strcat("multiset");
-    if(EXTRACT_UCHAR(t)!=T_MIXED)
-    {
-      my_strcat("(");
+      if(EXTRACT_UCHAR(t) == T_VOID)
+      {
+	t++;
+      }else{
+	if(s++) my_strcat(", ");
+	t=low_describe_type(t);
+	my_strcat(" ...");
+      }
+      my_strcat(" : ");
       t=low_describe_type(t);
       my_strcat(")");
-    }else{
-      t++;
+      break;
     }
-    break;
-
-  case T_NOT:
-    my_strcat("!");
-    t=low_describe_type(t);
-    break;
-
-  case T_OR:
-    t=low_describe_type(t);
-    my_strcat(" | ");
-    t=low_describe_type(t);
-    break;
-
-  case T_AND:
-    t=low_describe_type(t);
-    my_strcat(" & ");
-    t=low_describe_type(t);
-    break;
     
-  case T_MAPPING:
-    my_strcat("mapping");
-    if(EXTRACT_UCHAR(t)==T_MIXED && EXTRACT_UCHAR(t+1)==T_MIXED)
-    {
-      t+=2;
-    }else{
-      my_strcat("(");
+    case T_ARRAY:
+      if(EXTRACT_UCHAR(t)==T_MIXED)
+      {
+	my_strcat("array");
+	t++;
+      }else{
+	t=low_describe_type(t);
+	my_strcat("*");
+      }
+      break;
+      
+    case T_MULTISET:
+      my_strcat("multiset");
+      if(EXTRACT_UCHAR(t)!=T_MIXED)
+      {
+	my_strcat("(");
+	t=low_describe_type(t);
+	my_strcat(")");
+      }else{
+	t++;
+      }
+      break;
+      
+    case T_NOT:
+      my_strcat("!");
+      t=low_describe_type(t);
+      break;
+      
+    case T_OR:
+      t=low_describe_type(t);
+      my_strcat(" | ");
       t=low_describe_type(t);
+      break;
+      
+    case T_AND:
+      t=low_describe_type(t);
+      my_strcat(" & ");
+      t=low_describe_type(t);
+      break;
+      
+    case T_MAPPING:
+      my_strcat("mapping");
+      if(EXTRACT_UCHAR(t)==T_MIXED && EXTRACT_UCHAR(t+1)==T_MIXED)
+      {
+	t+=2;
+      }else{
+	my_strcat("(");
+	t=low_describe_type(t);
       my_strcat(":");
       t=low_describe_type(t);
       my_strcat(")");
@@ -616,6 +696,12 @@ struct pike_string *describe_type(struct pike_string *type)
   return free_buf();
 }
 
+static int low_is_same_type(char *a, char *b)
+{
+  if(type_length(a) != type_length(b)) return 0;
+  return !MEMCMP(a,b,type_length(a));
+}
+
 static TYPE_T low_compile_type_to_runtime_type(char *t)
 {
   TYPE_T tmp;
@@ -627,14 +713,21 @@ static TYPE_T low_compile_type_to_runtime_type(char *t)
     if(tmp == low_compile_type_to_runtime_type(t+type_length(t)))
       return tmp;
 
-  case T_MANY:
-  case T_UNKNOWN:
-  case T_AND:
-  case T_NOT:
-    return T_MIXED;
+    default:
+      return T_MIXED;
 
-  default:
-    return EXTRACT_UCHAR(t);
+    case T_ARRAY:
+    case T_MAPPING:
+    case T_MULTISET:
+
+    case T_OBJECT:
+    case T_PROGRAM:
+    case T_FUNCTION:
+
+    case T_STRING:
+    case T_INT:
+    case T_FLOAT:
+      return EXTRACT_UCHAR(t);
   }
 }
 
@@ -674,9 +767,31 @@ static char *low_match_types(char *a,char *b, int flags)
     return low_match_types(a,b,flags);
 
   case T_NOT:
-    if(low_match_types(a+1,b,flags | B_EXACT | NO_MAX_ARGS))
+    if(low_match_types(a+1,b,(flags ^ B_EXACT ) | NO_MAX_ARGS))
       return 0;
     return a;
+
+    case T_ASSIGN:
+      ret=low_match_types(a+2,b,flags);
+      if(ret)
+      {
+	int m=EXTRACT_UCHAR(a+1)-'0';
+	if(!a_markers[m])
+	  a_markers[m]=b;
+	else if(!low_is_same_type(a_markers[m], b))
+	  a_markers[m]=mixed_type_string->str;
+      }
+      return ret;
+
+    case '0': case '1': case '2': case '3': case '4':
+    case '5': case '6': case '7': case '8': case '9':
+    {
+      int m=EXTRACT_UCHAR(a)-'0';
+      if(a_markers[m])
+	return low_match_types(a_markers[m], b, flags);
+      else
+	return low_match_types(mixed_type_string->str, b, flags);
+    }
   }
 
   switch(EXTRACT_UCHAR(b))
@@ -696,9 +811,31 @@ static char *low_match_types(char *a,char *b, int flags)
     return low_match_types(a,b,flags);
 
   case T_NOT:
-    if(low_match_types(a,b+1, flags | A_EXACT | NO_MAX_ARGS))
+    if(low_match_types(a,b+1, (flags ^ A_EXACT ) | NO_MAX_ARGS))
       return 0;
     return a;
+
+    case T_ASSIGN:
+      ret=low_match_types(a,b+2,flags);
+      if(ret)
+      {
+	int m=EXTRACT_UCHAR(b+1)-'0';
+	if(!b_markers[m])
+	  b_markers[m]=a;
+	else if(!low_is_same_type(b_markers[m], a))
+	  b_markers[m]=mixed_type_string->str;
+      }
+      return ret;
+
+    case '0': case '1': case '2': case '3': case '4':
+    case '5': case '6': case '7': case '8': case '9':
+    {
+      int m=EXTRACT_UCHAR(b)-'0';
+      if(b_markers[m])
+	return low_match_types(a, b_markers[m], flags);
+      else
+	return low_match_types(a, mixed_type_string->str, flags);
+    }
   }
 
   /* 'mixed' matches anything */
@@ -893,7 +1030,7 @@ static int low_get_return_type(char *a,char *b)
       while(EXTRACT_UCHAR(a)!=T_MANY) a+=type_length(a);
       a++;
       a+=type_length(a);
-      push_unfinished_type(a);
+      push_unfinished_type_with_markers(a, a_markers );
       return 1;
 
     case T_PROGRAM:
@@ -914,6 +1051,7 @@ int match_types(struct pike_string *a,struct pike_string *b)
 {
   CHECK_TYPE(a);
   CHECK_TYPE(b);
+  clear_markers();
   return 0!=low_match_types(a->str, b->str,0);
 }
 
@@ -1022,6 +1160,7 @@ static struct pike_string *debug_low_index_type(char *t, node *n)
 struct pike_string *index_type(struct pike_string *type, node *n)
 {
   struct pike_string *t;
+  clear_markers();
   t=low_index_type(type->str,n);
   if(!t) copy_shared_string(t,mixed_type_string);
   return t;
@@ -1144,6 +1283,7 @@ struct pike_string *check_call(struct pike_string *args,
 {
   CHECK_TYPE(args);
   CHECK_TYPE(type);
+  clear_markers();
   type_stack_mark();
   max_correct_args=0;
   
@@ -1160,6 +1300,7 @@ INT32 get_max_args(struct pike_string *type)
 {
   INT32 ret,tmp=max_correct_args;
   CHECK_TYPE(type);
+  clear_markers();
   type=check_call(function_type_string, type);
   if(type) free_string(type);
   ret=max_correct_args;
diff --git a/src/program.c b/src/program.c
index 7ccef474a82852d8873ed7ffbd400c9d6b13e0cb..93496fc5817305dc5b144cd5bf60402fdaa5ab82 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.64 1998/02/27 08:39:21 hubbe Exp $");
+RCSID("$Id: program.c,v 1.65 1998/03/01 11:40:47 hubbe Exp $");
 #include "program.h"
 #include "object.h"
 #include "dynamic_buffer.h"
@@ -1027,9 +1027,21 @@ void low_inherit(struct program *p,
     {
       if(parent)
       {
-	inherit.parent=parent;
-	inherit.parent_identifier=parent_identifier;
-	inherit.parent_offset=0;
+	if(parent->next == parent)
+	{
+	  struct object *o;
+	  for(o=fake_object->parent;o!=parent;o=o->parent)
+	  {
+#ifdef DEBUG
+	    if(!o) fatal("low_inherit with odd fake_object as parent!\n");
+#endif
+	    inherit.parent_offset++;
+	  }
+	}else{
+	  inherit.parent=parent;
+	  inherit.parent_identifier=parent_identifier;
+	  inherit.parent_offset=0;
+	}
       }else{
 	inherit.parent_offset+=parent_offset;
       }
@@ -1864,9 +1876,9 @@ void store_linenumber(INT32 current_line, struct pike_string *current_file)
  */
 char *get_line(unsigned char *pc,struct program *prog,INT32 *linep)
 {
-  char *file;
-  INT32 off,line,offset;
-  char *cnt;
+  static char *file, *cnt;
+  static INT32 off,line,pid;
+  INT32 offset;
 
   if (prog == 0) return "Unkown program";
   offset = pc - prog->program;
@@ -1877,9 +1889,14 @@ char *get_line(unsigned char *pc,struct program *prog,INT32 *linep)
     return "Optimizer";
   }
 
-  cnt=prog->linenumbers;
-  off=line=0;
-  file="Line not found";
+  if(prog->id != pid || offset < off)
+  {
+    cnt=prog->linenumbers;
+    off=line=0;
+    file="Line not found";
+    pid=prog->id;
+  }
+
   if (offset > (INT32)prog->num_program || offset<0)
     return file;
 
diff --git a/src/stralloc.c b/src/stralloc.c
index 99fca6845e2042d2a41d034c6c8528b0782c0dd7..7175b9828ac6da9b484d2272dc69db5f0ba2c242 100644
--- a/src/stralloc.c
+++ b/src/stralloc.c
@@ -32,20 +32,40 @@ static unsigned int StrHash(const char *s,int len)
   return full_hash_value % htable_size;
 }
 
+#ifdef DEBUG
 #ifdef DEBUG_MALLOC
+#define DM(X) X
+#else
+#define DM(X)
+#endif
+
 static void locate_problem(int (*isproblem)(struct pike_string *))
 {
   unsigned INT32 e;
   struct pike_string *s;
-  struct memhdr *yes=alloc_memhdr();
-  struct memhdr *no=alloc_memhdr();
+  DM(struct memhdr *yes=alloc_memhdr());
+  DM(struct memhdr *no=alloc_memhdr());
 
   for(e=0;e<htable_size;e++)
+  {
     for(s=base_table[e];s;s=s->next)
-      add_marks_to_memhdr(isproblem(s)?yes:no,s);
+    {
+      if(isproblem(s))
+      {
+	fprintf(stderr,"***Guilty string:\n");
+	debug_dump_pike_string(s, 70);
+	DM(add_marks_to_memhdr(yes,s));
+      }else{
+	DM(add_marks_to_memhdr(no,s));
+      }
+    }
+  }
 
-  fprintf(stderr,"Plausible problem location(s):\n");
-  dump_memhdr_locations(yes,no);
+  DM(fprintf(stderr,"Plausible problem location(s):\n"));
+  DM(dump_memhdr_locations(yes,0));
+
+  DM(fprintf(stderr,"More Plausible problem location(s):\n"));
+  DM(dump_memhdr_locations(yes,no));
 }
 
 static int has_zero_refs(struct pike_string *s)
@@ -54,7 +74,7 @@ static int has_zero_refs(struct pike_string *s)
 }
 static int wrong_hash(struct pike_string *s)
 {
-  return s->hval != StrHash(s->str, s->len);
+  return (s->hval % htable_size) != StrHash(s->str, s->len);
 }
 static int improper_zero_termination(struct pike_string *s)
 {
@@ -196,6 +216,10 @@ struct pike_string *end_shared_string(struct pike_string *s)
   len=s->len;
   h=StrHash(s->str,len);
   s2=internal_findstring(s->str,len,h);
+#ifdef DEBUG
+  if(s2==s) 
+    fatal("end_shared_string called twice! (or something like that)\n");
+#endif
 
   if(s2)
   {
@@ -450,7 +474,7 @@ struct pike_string *debug_findstring(const struct pike_string *foo)
 void debug_dump_pike_string(struct pike_string *s, INT32 max)
 {
   INT32 e;
-  fprintf(stderr,"0x%p: %ld refs, len=%ld, hval=%lux (%lux)\n",
+  fprintf(stderr,"0x%p: %ld refs, len=%ld, hval=%lux (%lx)\n",
 	  s,
 	  (long)s->refs,
 	  (long)s->len,
diff --git a/src/svalue.h b/src/svalue.h
index 169b2f9aa79e79af8c08520ae86b5e2b5c6d448f..95e565a56874cc60a8b2c1f17f6e59a56c15878b 100644
--- a/src/svalue.h
+++ b/src/svalue.h
@@ -88,6 +88,7 @@ struct svalue
 #define T_VOID 16
 #define T_MANY 17
 
+#define T_ASSIGN 245
 #define T_DELETED 246
 #define T_NOT 247
 #define T_AND 248