diff --git a/src/ChangeLog b/src/ChangeLog
index 2f9260b147d6894e42de5f19f5369429aca00f88..41124fce848bf58e67ff11e10cc336c510793fce 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,10 @@
+Sat Mar  8 04:31:29 1997  Fredrik Hubinette  <hubbe@cytocin.hubbe.net>
+
+	* added new efuns `[] and `->
+	* type checking improved:
+	* function and program are now almost interchangeable.
+	* function and object are now almost interchangeable.
+
 Thu Mar  6 21:19:28 1997  Fredrik Hubinette  <hubbe@cytocin.hubbe.net>
 
 	* pike_types.c: recurseive compiling bugs fixed
diff --git a/src/interpret.c b/src/interpret.c
index aa29707faee22bd210dc806f1476de630cfece83..8bb77beff294465888e7d256de194629cfe66f64 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.28 1997/03/07 05:21:45 hubbe Exp $");
+RCSID("$Id: interpret.c,v 1.29 1997/03/08 12:54:06 hubbe Exp $");
 #include "interpret.h"
 #include "object.h"
 #include "program.h"
@@ -1072,7 +1072,7 @@ static void eval_instruction(unsigned char *pc)
 
       CASE(F_INDEX);
     do_index:
-      f_index();
+      o_index();
       print_return_value();
       break;
 
diff --git a/src/lex.c b/src/lex.c
index 1531d9898f2c762053cb04d7d4d315b142495e6e..01e9e894a39ddddc121c6944cf0b5717b7f67112 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.15 1997/01/31 23:09:02 hubbe Exp $");
+RCSID("$Id: lex.c,v 1.16 1997/03/08 12:54:06 hubbe Exp $");
 #include "language.h"
 #include "array.h"
 #include "lex.h"
@@ -1832,7 +1832,7 @@ static void calcC()
   {
     low_lex();
     calc1();
-    f_index();
+    f_index(2);
     if(lookahead!=']')
       error("Missing ']'\n");
     else
diff --git a/src/opcodes.c b/src/opcodes.c
index 0d3d6a21836829523593740ac8baf061bf3b038b..65cba860193749752e3983aa19bcedc6a42419fe 100644
--- a/src/opcodes.c
+++ b/src/opcodes.c
@@ -65,7 +65,7 @@ void index_no_free(struct svalue *to,struct svalue *what,struct svalue *ind)
   }
 }
 
-void f_index()
+void o_index()
 {
   index_no_free(sp,sp-2,sp-1);
   sp++;
diff --git a/src/opcodes.h b/src/opcodes.h
index 67e1db71fe63afc75f3c479b5ead795c2a34fba9..5993d54a06604b759582799e8e072ef6e8cb3e76 100644
--- a/src/opcodes.h
+++ b/src/opcodes.h
@@ -8,7 +8,8 @@
 
 /* Prototypes begin here */
 void index_no_free(struct svalue *to,struct svalue *what,struct svalue *ind);
-void f_index();
+void o_index();
+void cast(struct pike_string *s);
 void f_cast();
 void f_sscanf(INT32 args);
 /* Prototypes end here */
diff --git a/src/operators.c b/src/operators.c
index 42f525efeb78189bcfeb8d2aa5919fc6f0c3bde1..66e82299e06eb87188539d46175532089a587fe8 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.9 1997/02/19 05:04:19 hubbe Exp $");
+RCSID("$Id: operators.c,v 1.10 1997/03/08 12:54:07 hubbe Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "multiset.h"
@@ -1217,6 +1217,44 @@ void o_range()
   }
 }
 
+void f_index(INT32 args)
+{
+  switch(args)
+  {
+  case 0:
+  case 1:
+    error("Too few arguments to `[]\n");
+    break;
+  case 2:
+    if(sp[-1].type==T_STRING) sp[-1].subtype=0;
+    o_index();
+    break;
+  case 3:
+    o_range();
+    break;
+  default:
+    error("Too manu arguments to `[]\n");
+  }
+}
+
+void f_arrow(INT32 args)
+{
+  switch(args)
+  {
+  case 0:
+  case 1:
+    error("Too few arguments to `->\n");
+    break;
+  case 2:
+    if(sp[-1].type==T_STRING)
+      sp[-1].subtype=1;
+    o_index();
+    break;
+  default:
+    error("Too manu arguments to `->\n");
+  }
+}
+
 void f_sizeof(INT32 args)
 {
   INT32 tmp;
@@ -1241,6 +1279,12 @@ static int generate_sizeof(node *n)
 
 void init_operators()
 {
+  add_efun2("`[]",f_index,
+	    "function(string,int:int)|function(object,string:mixed)|function(array,int:mixed)|function(mapping,mixed:mixed)|function(multiset,mixed:int)|function(string,int,int:string)|function(array,int,int:array)",OPT_TRY_OPTIMIZE,0,0);
+
+  add_efun2("`->",f_arrow,
+	    "function(object|mapping|multiset,string:mixed)",OPT_TRY_OPTIMIZE,0,0);
+
   add_efun2("`==",f_eq,"function(mixed,mixed:int)",OPT_TRY_OPTIMIZE,0,generate_comparison);
   add_efun2("`!=",f_ne,"function(mixed,mixed:int)",OPT_TRY_OPTIMIZE,0,generate_comparison);
   add_efun2("`!",f_not,"function(mixed:int)",OPT_TRY_OPTIMIZE,0,generate_not);
diff --git a/src/pike_types.c b/src/pike_types.c
index e1cb7f65162e66bf8de9838d7dcea7e908336798..0f18b28531c432c904a015a5e31043f1d5dc3cec 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.17 1997/03/07 05:21:46 hubbe Exp $");
+RCSID("$Id: pike_types.c,v 1.18 1997/03/08 12:54:08 hubbe Exp $");
 #include <ctype.h>
 #include "svalue.h"
 #include "pike_types.h"
@@ -26,6 +26,9 @@ int max_correct_args;
 static void internal_parse_type(char **s);
 static int type_length(char *t);
 
+#define TWOT(X,Y) (((X) << 8)+(Y))
+#define EXTRACT_TWOT(X,Y) TWOT(EXTRACT_UCHAR(X), EXTRACT_UCHAR(Y))
+
 /*
  * basic types are represented by just their value in a string
  * basic type are string, int, float, object and program
@@ -699,18 +702,13 @@ static char *low_match_types(char *a,char *b, int flags)
   if(EXTRACT_UCHAR(a) == T_MIXED && !(flags & A_EXACT)) return a;
   if(EXTRACT_UCHAR(b) == T_MIXED && !(flags & B_EXACT)) return a;
 
-  /* Special case (tm) */
-
-  /* Handle cloning with prog() */
-  if(EXTRACT_UCHAR(a) == T_PROGRAM &&
-     EXTRACT_UCHAR(b)==T_FUNCTION)
+  /* Special cases (tm) */
+  switch(EXTRACT_TWOT(a,b))
   {
+  case TWOT(T_PROGRAM, T_FUNCTION):
+  case TWOT(T_FUNCTION, T_PROGRAM):
     return a;
-  }
-
-  /* Handle the `() operator */
-  if(EXTRACT_UCHAR(a) == T_OBJECT &&
-     EXTRACT_UCHAR(b)==T_FUNCTION)
+  case TWOT(T_OBJECT, T_FUNCTION):
   {
     struct program *p;
     if(p=id_to_program(EXTRACT_INT(a+1)))
@@ -722,6 +720,19 @@ static char *low_match_types(char *a,char *b, int flags)
     return a;
   }
 
+  case TWOT(T_FUNCTION, T_OBJECT):
+  {
+    struct program *p;
+    if(p=id_to_program(EXTRACT_INT(b+1)))
+    {
+      int i=p->lfuns[LFUN_CALL];
+      if(i == -1) return 0;
+      return low_match_types(a, ID_FROM_INT(p, i)->type->str, flags);
+    }
+    return a;
+  }
+  }
+
   if(EXTRACT_UCHAR(a) != EXTRACT_UCHAR(b)) return 0;
 
   ret=a;
@@ -1149,6 +1160,42 @@ struct pike_string *get_type_of_svalue(struct svalue *s)
     reference_shared_string(ret);
     return ret;
 
+  case T_PROGRAM:
+  {
+    char *a;
+    int id=s->u.program->lfuns[LFUN_CREATE];
+    if(id>=0)
+    {
+      a=ID_FROM_INT(s->u.program, id)->type->str;
+    }else{
+      a=function_type_string->str;
+    }
+    if(EXTRACT_UCHAR(a)==T_FUNCTION)
+    {
+      type_stack_mark();
+      push_type_int(s->u.program->id);
+      push_type(T_OBJECT);
+      
+      type_stack_mark();
+      a++;
+      while(EXTRACT_UCHAR(a)!=T_MANY)
+      {
+	type_stack_mark();
+	push_unfinished_type(a);
+	type_stack_reverse();
+	a+=type_length(a);
+      }
+      a++;
+      push_type(T_MANY);
+      type_stack_mark();
+      push_unfinished_type(a);
+      type_stack_reverse();
+      type_stack_reverse();
+      push_type(T_FUNCTION);
+      return pop_unfinished_type();
+    }
+  }
+
   default:
     type_stack_mark();
     push_type(s->type);
diff --git a/src/testsuite.in b/src/testsuite.in
index d6cdb7f52cca0bdd4e16ad64755b8949d17a143b..7dd2e80402cafab4d152808c3d486d717761ea22 100644
--- a/src/testsuite.in
+++ b/src/testsuite.in
@@ -1,4 +1,5 @@
-test_true([["$Id: testsuite.in,v 1.32 1997/03/01 03:30:49 hubbe Exp $"]])
+test_true([["$Id: testsuite.in,v 1.33 1997/03/08 12:54:09 hubbe Exp $"]])
+test_true([[lambda(function f) {return 1;}(object_program(this_object()));]])
 test_eq([[class { int `()(){ return 4711; } }()(); ]],4711)
 teste_eval_error(mixed foo=({}); sort(@foo); )
 test_compile_error([[int foo() { return 1} ; constant foo=(["foo":foo]); return foo->foo();]])