Browse Source

Added support for numeric & scalar type hint as defined within

http://wiki.php.net/rfc/typecheckingstrictandweak RFC
experimental/lemon
Ilia Alshanetsky 16 years ago
parent
commit
33fae4caa0
  1. 37
      Zend/tests/hint/param_type_hint_019.phpt
  2. 15
      Zend/tests/hint/param_type_hint_020.phpt
  3. 46
      Zend/tests/hint/param_type_hint_021.phpt
  4. 2
      Zend/zend.h
  5. 4
      Zend/zend_API.c
  6. 13
      Zend/zend_compile.c
  7. 12
      Zend/zend_execute.c
  8. 8
      Zend/zend_language_parser.y
  9. 3565
      Zend/zend_language_scanner.c
  10. 16
      Zend/zend_language_scanner.l
  11. 2
      Zend/zend_language_scanner_defs.h

37
Zend/tests/hint/param_type_hint_019.phpt

@ -0,0 +1,37 @@
--TEST--
Parameter type hint - scalar type hints
--FILE--
<?php
function x($error, $msg) { var_dump($msg); }
set_error_handler('x', E_RECOVERABLE_ERROR);
function foo(scalar $param) { var_dump($param); }
foo(1);
foo(true);
foo(NULL);
foo(array(1));
foo("foo");
foo(111.222);
foo(new Stdclass);
foo(tmpfile());
?>
--EXPECTF--
int(1)
bool(true)
string(%d) "Argument 1 passed to foo() must be of the type scalar, null given, called in %s on line %d and defined"
NULL
string(%d) "Argument 1 passed to foo() must be of the type scalar, array given, called in %s on line %d and defined"
array(1) {
[0]=>
int(1)
}
string(3) "foo"
float(111.222)
string(%d) "Argument 1 passed to foo() must be of the type scalar, object given, called in %s on line %d and defined"
object(stdClass)#1 (0) {
}
string(%d) "Argument 1 passed to foo() must be of the type scalar, resource given, called in %s on line %d and defined"
resource(4) of type (stream)

15
Zend/tests/hint/param_type_hint_020.phpt

@ -0,0 +1,15 @@
--TEST--
Parameter type hint - scalar type hints, default value
--FILE--
<?php
function bar1(scalar $param = null) {}
function bar2(scalar $param = 123) {}
function bar3(scalar $param = false) {}
function bar4(scalar $param = 988.99) {}
function bar5(scalar $param = "1233") {}
function bar6(scalar $param = array(1,2,3)) {}
?>
--EXPECTF--
Fatal error: Default value for parameters with scalar type hint can only be scalar or NULL in %s on line %d

46
Zend/tests/hint/param_type_hint_021.phpt

@ -0,0 +1,46 @@
--TEST--
Parameter type hint - numeric type hints
--FILE--
<?php
function x($error, $msg) { var_dump($msg); }
set_error_handler('x', E_RECOVERABLE_ERROR);
function foo(numeric $param) { var_dump($param); }
foo(1);
foo(true);
foo(NULL);
foo(array(1));
foo("foo");
foo("123.33");
foo("123");
foo("");
foo(111.222);
foo(new Stdclass);
foo(tmpfile());
?>
--EXPECTF--
int(1)
string(%d) "Argument 1 passed to foo() must be of the type numeric, boolean given, called in %s on line %d and defined"
bool(true)
string(%d) "Argument 1 passed to foo() must be of the type numeric, null given, called in %s on line %d and defined"
NULL
string(%d) "Argument 1 passed to foo() must be of the type numeric, array given, called in %s on line %d and defined"
array(1) {
[0]=>
int(1)
}
string(%d) "Argument 1 passed to foo() must be of the type numeric, string given, called in %s on line %d and defined"
string(3) "foo"
string(6) "123.33"
string(3) "123"
string(%d) "Argument 1 passed to foo() must be of the type numeric, string given, called in %s on line %d and defined"
string(0) ""
float(111.222)
string(%d) "Argument 1 passed to foo() must be of the type numeric, object given, called in %s on line %d and defined"
object(stdClass)#1 (0) {
}
string(%d) "Argument 1 passed to foo() must be of the type numeric, resource given, called in %s on line %d and defined"
resource(4) of type (stream)

2
Zend/zend.h

@ -571,6 +571,8 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
#define IS_CONSTANT_ARRAY 9
/* used for type-hinting only */
#define IS_CLASS 10
#define IS_SCALAR 11
#define IS_NUMERIC 12
/* Ugly hack to support constants as static array indices */
#define IS_CONSTANT_TYPE_MASK 0x00f

4
Zend/zend_API.c

@ -199,6 +199,10 @@ ZEND_API char *zend_get_type_by_const(int type) /* {{{ */
switch(type) {
case IS_BOOL:
return "boolean";
case IS_SCALAR:
return "scalar";
case IS_NUMERIC:
return "numeric";
case IS_LONG:
return "integer";
case IS_DOUBLE:

13
Zend/zend_compile.c

@ -1876,6 +1876,19 @@ void zend_do_receive_arg(zend_uchar op, znode *varname, const znode *offset, con
break;
/* scalar type hinting */
case IS_SCALAR:
if (op == ZEND_RECV_INIT && Z_TYPE(initialization->u.constant) != IS_ARRAY && Z_TYPE(initialization->u.constant) != IS_CONSTANT_ARRAY) {
break;
}
/* fall through */
/* scalar type hinting */
case IS_NUMERIC:
if (op == ZEND_RECV_INIT && (Z_TYPE(initialization->u.constant) == IS_LONG || Z_TYPE(initialization->u.constant) == IS_DOUBLE)) {
break;
}
/* fall through */
case IS_BOOL:
case IS_STRING:
case IS_LONG:

12
Zend/zend_execute.c

@ -685,6 +685,18 @@ static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zva
if (Z_TYPE_P(arg) == IS_NULL && cur_arg_info->allow_null) {
return 1;
}
if (cur_arg_info->type_hint == IS_SCALAR && Z_TYPE_P(arg) != IS_NULL && Z_TYPE_P(arg) != IS_ARRAY && Z_TYPE_P(arg) != IS_OBJECT && Z_TYPE_P(arg) != IS_RESOURCE) {
return 1;
}
if (cur_arg_info->type_hint == IS_NUMERIC && (
(Z_TYPE_P(arg) == IS_LONG || Z_TYPE_P(arg) == IS_DOUBLE)
|| (Z_TYPE_P(arg) == IS_STRING && is_numeric_string(Z_STRVAL_P(arg), Z_STRLEN_P(arg), NULL, NULL, 0))
)) {
return 1;
}
return zend_verify_arg_error(zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), "", zend_zval_type_name(arg) TSRMLS_CC);
}
return 1;

8
Zend/zend_language_parser.y

@ -69,7 +69,7 @@
%left '*' '/' '%'
%right '!'
%nonassoc T_INSTANCEOF
%right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@'
%right '~' T_INC T_DEC T_INT_CAST T_NUMERIC_CAST T_SCALAR_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@'
%right '['
%nonassoc T_NEW T_CLONE
%token T_EXIT
@ -136,6 +136,8 @@
%token T_DOUBLE_HINT
%token T_RESOURCE_HINT
%token T_OBJECT_HINT
%token T_SCALAR_HINT
%token T_NUMERIC_HINT
%token T_CLASS_C
%token T_METHOD_C
%token T_FUNC_C
@ -479,6 +481,8 @@ optional_class_type:
| T_DOUBLE_HINT { $$ = $1; $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_DOUBLE; }
| T_RESOURCE_HINT { $$ = $1; $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_RESOURCE; }
| T_OBJECT_HINT { $$ = $1; $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_OBJECT; }
| T_SCALAR_HINT { $$ = $1; $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_SCALAR; }
| T_NUMERIC_HINT { $$ = $1; $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_NUMERIC; }
| fully_qualified_class_name { $$ = $1; $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_CLASS; }
;
@ -712,6 +716,8 @@ expr_without_variable:
| T_ARRAY_CAST expr { zend_do_cast(&$$, &$2, IS_ARRAY TSRMLS_CC); }
| T_OBJECT_CAST expr { zend_do_cast(&$$, &$2, IS_OBJECT TSRMLS_CC); }
| T_BOOL_CAST expr { zend_do_cast(&$$, &$2, IS_BOOL TSRMLS_CC); }
| T_SCALAR_CAST expr { zend_do_cast(&$$, &$2, IS_SCALAR TSRMLS_CC); }
| T_NUMERIC_CAST expr { zend_do_cast(&$$, &$2, IS_NUMERIC TSRMLS_CC); }
| T_UNSET_CAST expr { zend_do_cast(&$$, &$2, IS_NULL TSRMLS_CC); }
| T_EXIT exit_expr { zend_do_exit(&$$, &$2 TSRMLS_CC); }
| '@' { zend_do_begin_silence(&$1 TSRMLS_CC); } expr { zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; }

3565
Zend/zend_language_scanner.c
File diff suppressed because it is too large
View File

16
Zend/zend_language_scanner.l

@ -1060,12 +1060,12 @@ NEWLINE ("\r"|"\n"|"\r\n")
return T_DOUBLE_CAST;
}
<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"string"{TABS_AND_SPACES}")" {
<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("string"|"binary"){TABS_AND_SPACES}")" {
return T_STRING_CAST;
}
<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"binary"{TABS_AND_SPACES}")" {
return T_STRING_CAST;
<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"scalar"{TABS_AND_SPACES}")" {
return T_SCALAR_CAST;
}
<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"array"{TABS_AND_SPACES}")" {
@ -1186,6 +1186,16 @@ NEWLINE ("\r"|"\n"|"\r\n")
return T_STRING_HINT;
}
<ST_IN_SCRIPTING>"scalar"{TABS_AND_SPACES}[ \r\n\t&]*"$" {
yyless(6);
return T_SCALAR_HINT;
}
<ST_IN_SCRIPTING>"numeric"{TABS_AND_SPACES}[ \r\n\t&]*"$" {
yyless(7);
return T_NUMERIC_HINT;
}
<ST_IN_SCRIPTING>("int"|"integer"|"long"){TABS_AND_SPACES}[ \r\n\t&]*"$" {
if (yytext[3] == 'e') {
yyless((sizeof("integer") - 1));

2
Zend/zend_language_scanner_defs.h

@ -1,4 +1,4 @@
/* Generated by re2c 0.13.5 on Sun May 23 14:06:04 2010 */
/* Generated by re2c 0.13.5 on Mon May 24 14:07:57 2010 */
#line 3 "Zend/zend_language_scanner_defs.h"
enum YYCONDTYPE {

Loading…
Cancel
Save