diff --git a/src/pike_types.c b/src/pike_types.c
index 2da8d46a255d1d536c62e7e88c58091b60ed2856..a74663a74c5cb5f6cf9209c900aa6148602d2f6a 100644
--- a/src/pike_types.c
+++ b/src/pike_types.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: pike_types.c,v 1.71 1999/11/23 23:28:18 hubbe Exp $");
+RCSID("$Id: pike_types.c,v 1.72 1999/11/24 21:44:02 hubbe Exp $");
 #include <ctype.h>
 #include "svalue.h"
 #include "pike_types.h"
@@ -25,6 +25,8 @@ RCSID("$Id: pike_types.c,v 1.71 1999/11/23 23:28:18 hubbe Exp $");
 #include "pike_memory.h"
 #include "bignum.h"
 
+/* #define PIKE_TYPE_DEBUG */
+
 int max_correct_args;
 
 static void internal_parse_type(char **s);
@@ -261,10 +263,14 @@ static void push_unfinished_type_with_markers(char *s, struct pike_string **am)
 	{
 	  push_finished_type_backwards(am[c-'0']);
 	}else{
-	  push_type(T_MIXED);
+	  push_type(T_ZERO);
 	}
 	break;
 #endif
+      case T_ASSIGN:
+	push_type(c);
+	push_type(EXTRACT_UCHAR(s+ ++e));
+	break;
 
       case T_INT:
 	push_type(c);
@@ -951,6 +957,10 @@ static void very_low_or_pike_types(char *to_push, char *not_push)
     very_low_or_pike_types(to_push, not_push);
     to_push+=type_length(to_push);
   }
+  /* FIXME:
+   * this might use the 'le' operator
+   */
+
   if(!low_find_exact_type_match(to_push, not_push, T_OR))
   {
     push_unfinished_type(to_push);
@@ -1226,11 +1236,61 @@ static struct pike_string *low_object_lfun_type(char *t, short lfun)
 #define NO_MAX_ARGS 4
 #define NO_SHORTCUTS 8
 
+
+#ifdef PIKE_TYPE_DEBUG
+static int indent=0;
+#endif
+
 /*
  * match two type strings, return zero if they don't match, and return
  * the part of 'a' that _did_ match if it did.
  */
 static char *low_match_types(char *a,char *b, int flags)
+#ifdef PIKE_TYPE_DEBUG
+{
+  int e;
+  char *s;
+  char *low_match_types2(char *a,char *b, int flags);
+
+  init_buf();
+  for(e=0;e<indent;e++) my_strcat("  ");
+  my_strcat("low_match_types(");
+  low_describe_type(a);
+  if(type_length(a) + type_length(b) > 10)
+  {
+    my_strcat(",\n");
+    for(e=0;e<indent;e++) my_strcat("  ");
+    my_strcat("                ");
+    low_describe_type(b);
+  }else{
+    my_strcat(", ");
+    low_describe_type(b);
+  }
+  my_strcat(");\n");
+  fprintf(stderr,"%s",(s=simple_free_buf()));
+  free(s);
+  indent++;
+
+  a=low_match_types2(a,b,flags);
+
+  indent--;
+  init_buf();
+  for(e=0;e<indent;e++) my_strcat("  ");
+  my_strcat("= ");
+  if(a)
+    low_describe_type(a);
+  else
+    my_strcat("NULL");
+  my_strcat("\n");
+  fprintf(stderr,"%s",(s=simple_free_buf()));
+  free(s);
+
+  return a;
+}
+
+static char *low_match_types2(char *a,char *b, int flags)
+#endif
+
 {
   int correct_args;
   char *ret;
@@ -1268,10 +1328,36 @@ static char *low_match_types(char *a,char *b, int flags)
       if(ret && EXTRACT_UCHAR(b)!=T_VOID)
       {
 	int m=EXTRACT_UCHAR(a+1)-'0';
+	struct pike_string *tmp;
+	type_stack_mark();
+	push_unfinished_type_with_markers(b, b_markers);
+	tmp=pop_unfinished_type();
+
 	type_stack_mark();
-	low_or_pike_types(a_markers[m] ? a_markers[m]->str : 0,b);
+	medium_or_pike_types(a_markers[m], tmp);
 	if(a_markers[m]) free_string(a_markers[m]);
+	free_string(tmp);
 	a_markers[m]=pop_unfinished_type();
+
+#ifdef PIKE_TYPE_DEBUG
+	{
+	  char *s;
+	  int e;
+	  init_buf();
+	  for(e=0;e<indent;e++) my_strcat("  ");
+	  my_strcat("a_markers[");
+	  my_putchar(m+'0');
+	  my_strcat("]=");
+	  low_describe_type(a_markers[m]->str);
+	  my_strcat("\n");
+	  fprintf(stderr,"%s",(s=simple_free_buf()));
+	  free(s);
+	}
+#endif
+#ifdef PIKE_DEBUG
+	if(a_markers[m]->str[0] == m+'0')
+	  fatal("Cyclic type!\n");
+#endif
       }
       return ret;
 
@@ -1280,7 +1366,16 @@ static char *low_match_types(char *a,char *b, int flags)
     {
       int m=EXTRACT_UCHAR(a)-'0';
       if(a_markers[m])
+      {
+#ifdef PIKE_DEBUG
+	if(a_markers[m]->str[0] == EXTRACT_UCHAR(a))
+	  fatal("Cyclic type!\n");
+	if(EXTRACT_UCHAR(a_markers[m]->str) == T_OR &&
+	  a_markers[m]->str[1] == EXTRACT_UCHAR(a))
+	  fatal("Cyclic type!\n");
+#endif
 	return low_match_types(a_markers[m]->str, b, flags);
+      }
       else
 	return low_match_types(mixed_type_string->str, b, flags);
     }
@@ -1318,10 +1413,35 @@ static char *low_match_types(char *a,char *b, int flags)
       if(ret && EXTRACT_UCHAR(a)!=T_VOID)
       {
 	int m=EXTRACT_UCHAR(b+1)-'0';
+	struct pike_string *tmp;
 	type_stack_mark();
-	low_or_pike_types(b_markers[m] ? b_markers[m]->str : 0,a);
+	push_unfinished_type_with_markers(a, a_markers);
+	tmp=pop_unfinished_type();
+
+	type_stack_mark();
+	medium_or_pike_types(b_markers[m], tmp);
 	if(b_markers[m]) free_string(b_markers[m]);
+	free_string(tmp);
 	b_markers[m]=pop_unfinished_type();
+#ifdef PIKE_TYPE_DEBUG
+	{
+	  char *s;
+	  int e;
+	  init_buf();
+	  for(e=0;e<indent;e++) my_strcat("  ");
+	  my_strcat("b_markers[");
+	  my_putchar(m+'0');
+	  my_strcat("]=");
+	  low_describe_type(b_markers[m]->str);
+	  my_strcat("\n");
+	  fprintf(stderr,"%s",(s=simple_free_buf()));
+	  free(s);
+	}
+#endif
+#ifdef PIKE_DEBUG
+	if(b_markers[m]->str[0] == m+'0')
+	  fatal("Cyclic type!\n");
+#endif
       }
       return ret;
 
@@ -1330,19 +1450,69 @@ static char *low_match_types(char *a,char *b, int flags)
     {
       int m=EXTRACT_UCHAR(b)-'0';
       if(b_markers[m])
+      {
+#ifdef PIKE_DEBUG
+	if(b_markers[m]->str[0] == EXTRACT_UCHAR(b))
+	  fatal("Cyclic type!\n");
+#endif
 	return low_match_types(a, b_markers[m]->str, flags);
+      }
       else
 	return low_match_types(a, mixed_type_string->str, flags);
     }
   }
 
   /* 'mixed' matches anything */
-  if(EXTRACT_UCHAR(b) == T_MIXED && !(flags & B_EXACT)) return a;
-  if(EXTRACT_UCHAR(a) == T_ZERO && !(flags & A_EXACT) &&
-     EXTRACT_UCHAR(b) != T_VOID) return a;
-  if(EXTRACT_UCHAR(a) == T_MIXED && !(flags & A_EXACT)) return a;
-  if(EXTRACT_UCHAR(b) == T_ZERO && !(flags & B_EXACT) &&
-     EXTRACT_UCHAR(a) != T_VOID) return a;
+
+  if((EXTRACT_UCHAR(a) == T_ZERO && !(flags & A_EXACT) &&
+      EXTRACT_UCHAR(b) != T_VOID) ||
+     (EXTRACT_UCHAR(a) == T_MIXED && !(flags & A_EXACT)))
+  {
+#if 1
+    switch(EXTRACT_UCHAR(b))
+    {
+      /* These types can contain sub-types */
+      case T_ARRAY:
+	low_match_types(array_type_string->str,b , flags);
+	break;
+      case T_MAPPING:
+	low_match_types(mapping_type_string->str,b, flags);
+	break;
+      case T_FUNCTION:
+	low_match_types(function_type_string->str,b, flags);
+	break;
+      case T_MULTISET:
+	low_match_types(multiset_type_string->str,b, flags);
+	break;
+    }
+#endif
+    return a;
+  }
+
+  if((EXTRACT_UCHAR(b) == T_MIXED && !(flags & B_EXACT)) ||
+     (EXTRACT_UCHAR(b) == T_ZERO && !(flags & B_EXACT) &&
+      EXTRACT_UCHAR(a) != T_VOID))
+  {
+#if 1
+    switch(EXTRACT_UCHAR(a))
+    {
+      /* These types can contain sub-types */
+      case T_ARRAY:
+	low_match_types(a , array_type_string->str, flags);
+	break;
+      case T_MAPPING:
+	low_match_types(a , mapping_type_string->str, flags);
+	break;
+      case T_FUNCTION:
+	low_match_types(a , function_type_string->str, flags);
+	break;
+      case T_MULTISET:
+	low_match_types(a , multiset_type_string->str, flags);
+	break;
+    }
+#endif
+    return a;
+  }
 
 
   /* Special cases (tm) */
@@ -1543,10 +1713,31 @@ static int low_pike_types_le(char *a,char *b)
     if(ret && EXTRACT_UCHAR(b)!=T_VOID)
     {
       int m=EXTRACT_UCHAR(a+1)-'0';
+      struct pike_string *tmp;
       type_stack_mark();
-      low_or_pike_types(a_markers[m] ? a_markers[m]->str : 0,b);
+      push_unfinished_type_with_markers(b, b_markers);
+      tmp=pop_unfinished_type();
+
+      type_stack_mark();
+      medium_or_pike_types(a_markers[m], tmp);
       if(a_markers[m]) free_string(a_markers[m]);
+      free_string(tmp);
       a_markers[m]=pop_unfinished_type();
+#ifdef PIKE_TYPE_DEBUG
+      {
+	char *s;
+	int e;
+	init_buf();
+	for(e=0;e<indent;e++) my_strcat("  ");
+	my_strcat("a_markers[");
+	my_putchar(m+'0');
+	my_strcat("]=");
+	low_describe_type(a_markers[m]->str);
+	my_strcat("\n");
+	fprintf(stderr,"%s",(s=simple_free_buf()));
+	free(s);
+      }
+#endif
     }
     return ret;
 
@@ -1587,10 +1778,31 @@ static int low_pike_types_le(char *a,char *b)
     if(ret && EXTRACT_UCHAR(a)!=T_VOID)
     {
       int m=EXTRACT_UCHAR(b+1)-'0';
+      struct pike_string *tmp;
       type_stack_mark();
-      low_or_pike_types(b_markers[m] ? b_markers[m]->str : 0,a);
+      push_unfinished_type_with_markers(a, a_markers);
+      tmp=pop_unfinished_type();
+      
+      type_stack_mark();
+      medium_or_pike_types(b_markers[m], tmp);
       if(b_markers[m]) free_string(b_markers[m]);
+      free_string(tmp);
       b_markers[m]=pop_unfinished_type();
+#ifdef PIKE_TYPE_DEBUG
+      {
+	char *s;
+	int e;
+	init_buf();
+	for(e=0;e<indent;e++) my_strcat("  ");
+	my_strcat("b_markers[");
+	my_putchar(m+'0');
+	my_strcat("]=");
+	low_describe_type(b_markers[m]->str);
+	my_strcat("\n");
+	fprintf(stderr,"%s",(s=simple_free_buf()));
+	free(s);
+      }
+#endif
     }
     return ret;
 
@@ -1992,7 +2204,10 @@ static struct pike_string *debug_low_index_type(char *t, node *n)
     return make_shared_binary_string(t, type_length(t));
 
   case T_ARRAY:
-    if(n && low_match_types(string_type_string->str,CDR(n)->type->str,0))
+    if(n &&
+       (CDR(n)->token == F_CONSTANT ?
+       CDR(n)->u.sval.type == T_STRING :
+       low_match_types(string_type_string->str,CDR(n)->type->str,0)))
     {
       struct pike_string *a=low_index_type(t,n);
       if(!a)