On Thu, 2003-03-27 at 17:16, Timm Friebe wrote:
> I've implemented an additional feature for type hints that will throw an
> exception instead of bailing out in case an incorrect type is passed.
[...LONG disussion...]

After reading through a bunch of mails this generated, I get the idea
that most people here would be happier with an E_WARNING and the
function not being executed.

That gives:
- the OOP purist the possibility to throw an exception (in a userland
  error handler)
- the SOAP server a way to nicely recover
- the API designer a way to tell the user (s)he's messed up
- the "standard" programmer what (s)he's used to (PHP is quite
  forgiving in the way it handles incorrect argument types and
  usually warns about this)

Attached is the E_WARNING variant, an example script and its output.

- Timm
Index: Zend/ZEND_CHANGES
===================================================================
RCS file: /repository/ZendEngine2/ZEND_CHANGES,v
retrieving revision 1.55
diff -u -r1.55 ZEND_CHANGES
--- Zend/ZEND_CHANGES	7 Mar 2003 16:45:41 -0000	1.55
+++ Zend/ZEND_CHANGES	28 Mar 2003 17:09:53 -0000
@@ -177,6 +177,10 @@
           function b(Bar $bar) {
             // ...
           }
+          
+          function c([Bar] $bar) {
+            // ...
+          }
         }
 
         $a = new FooBar;
@@ -184,10 +188,14 @@
 
         $a->a($b);
         $a->b($b);
+        $a->c($b);
+        $a->c(NULL);
         ?>
 
       These class type hints are not checked upon compilation, as would
-      be the case in a typed language, but during runtime.
+      be the case in a typed language, but during runtime. Type hints in
+      square brackets (as seen in function "c") denote passing of NULL is
+      also allowed.
 
       This means that
 
@@ -202,6 +210,21 @@
             die('Argument 1 must be an instance of ClassName');
           }
         }
+        
+      and
+
+        function foo([ClassName] $object) {
+          // ...
+        }
+
+      is equivalent to
+
+        function foo($object) {
+          if (!is_null($object) && !($object instanceof ClassName)) {
+            die('Argument 1 must be an instance of ClassName');
+          }
+        }
+      .
 
       This syntax only applies to objects/classes, not built-in types.
 
Index: Zend/zend_execute.c
===================================================================
RCS file: /repository/ZendEngine2/zend_execute.c,v
retrieving revision 1.449
diff -u -r1.449 zend_execute.c
--- Zend/zend_execute.c	27 Mar 2003 17:57:47 -0000	1.449
+++ Zend/zend_execute.c	28 Mar 2003 17:09:54 -0000
@@ -4011,9 +4011,22 @@
 {
 	zval *arg = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R);
 	zend_class_entry *ce = EX_T(EX(opline)->op1.u.var).EA.class_entry;
+	int allowed;
+	
+	switch (Z_TYPE_P(arg)) {
+		case IS_OBJECT:
+			allowed= instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC);
+			break;
+			
+		case IS_NULL:
+			allowed= (EX(opline)->op1.op_type == IS_VAR);
+			break;
+			
+		default: 
+			allowed= 0;
+	}
 
-	if ((Z_TYPE_P(arg) != IS_OBJECT)
-		|| !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) {
+	if (!allowed) {
 		char *error_msg;
 
 		if (ce->ce_flags & ZEND_ACC_INTERFACE) {
@@ -4021,7 +4034,9 @@
 		} else {
 			error_msg = "be an instance of";
 		}
-		zend_error(E_ERROR, "Argument %d must %s %s", EX(opline)->extended_value, error_msg, ce->name);
+		
+		zend_error(E_WARNING, "Argument %d must %s %s", EX(opline)->extended_value, error_msg, ce->name);
+		RETURN_FROM_EXECUTE_LOOP(execute_data);
 	}
 
 	NEXT_OPCODE();
Index: Zend/zend_language_parser.y
===================================================================
RCS file: /repository/ZendEngine2/zend_language_parser.y,v
retrieving revision 1.105
diff -u -r1.105 zend_language_parser.y
--- Zend/zend_language_parser.y	26 Mar 2003 20:42:23 -0000	1.105
+++ Zend/zend_language_parser.y	28 Mar 2003 17:09:55 -0000
@@ -453,7 +453,8 @@
 
 optional_class_type:
 		/* empty */		{ $$.op_type = IS_UNUSED; }
-	|	fully_qualified_class_name		{ $$ = $1; }
+	|	fully_qualified_class_name			{ $$ = $1; $$.op_type = IS_CONST; }
+	|	'[' fully_qualified_class_name ']'	{ $$ = $2; $$.op_type = IS_VAR; }
 ;
 
 function_call_parameter_list:

Attachment: hints.php
Description: application/php

Warning: Argument 1 must be an instance of date in 
/usr/home/thekid/devel/php/hints.php on line 42
object(article)#1 (3) {
  ["created_at"]=>
  object(date)#2 (1) {
    [""]=>
    int(1048871463)
  }
  ["lastchange"]=>
  NULL
  ["revisions"]=>
  array(0) {
  }
}
string(31) "Fri, 28 Mar 2003 18:11:03 +0100"

Warning: Argument 3 must be an instance of date in 
/usr/home/thekid/devel/php/hints.php on line 25
NULL

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to