Skip to content

Scalar Type Hints #998

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
c3c0f53
Scalar type hints with ZPP casting rules
hikari-no-yume Dec 13, 2014
75a225d
Do not make scalar type hints reserved words, merely reserve class name
hikari-no-yume Dec 27, 2014
d4dd2a9
Use new names of arg parsing functions
hikari-no-yume Dec 29, 2014
a13d134
Refactor scalar type hints implementation per Dmitry's patch
hikari-no-yume Dec 29, 2014
a03af7f
Fix class name prohibition to work for namespaced classes, too
hikari-no-yume Jan 4, 2015
1a28ad0
Forbid scalar type hint names for use, class_alias
hikari-no-yume Jan 6, 2015
5544e37
Inline
hikari-no-yume Jan 6, 2015
cc01e37
It Begins
hikari-no-yume Jan 10, 2015
02ec357
Per-file
hikari-no-yume Jan 12, 2015
fe663cc
Partial ZPP strictness implementation
hikari-no-yume Jan 13, 2015
ca49012
Add strict scalar types test
hikari-no-yume Jan 13, 2015
e1a2386
Shorten syntax to strict_types=1
hikari-no-yume Jan 25, 2015
b112c13
Test strict code calling weak code and vice-versa
hikari-no-yume Jan 25, 2015
2985944
Fix usage of zend_wrong_param_count in ext/mysqli
hikari-no-yume Jan 25, 2015
86b0685
Prefix zend_wrong_param_count with _ to discourage use
hikari-no-yume Jan 25, 2015
17b3707
Test strict code including weak code and vice-versa
hikari-no-yume Jan 25, 2015
c6e8048
Fix fix
hikari-no-yume Jan 25, 2015
187a95f
Test nested strict/weak function calls
hikari-no-yume Jan 25, 2015
0af3b7c
Test behaviour of weak type hints with references
hikari-no-yume Jan 25, 2015
cbbaea0
Fix merge error
hikari-no-yume Jan 29, 2015
c7719ab
Refactor typehint lookup
hikari-no-yume Feb 1, 2015
6b6b2b4
Implement scalar return types (strict only for now)
hikari-no-yume Feb 1, 2015
44ed070
Fix Gd usages of ZEND_WRONG_PARAM_COUNT, add usage note
hikari-no-yume Feb 1, 2015
5a7ac0f
Implement per-file strictness for scalar return types
hikari-no-yume Feb 1, 2015
0294485
Prevent "undefined variable opline" errors
hikari-no-yume Feb 2, 2015
b5513cd
Add scalar return types test
hikari-no-yume Feb 5, 2015
d6bea5b
Fixed use after free on the following code
dstogov Feb 10, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Refactor typehint lookup
  • Loading branch information
hikari-no-yume committed Feb 10, 2015
commit c7719ab4e5e49cdcef350a873ce4067bab3b7c02
78 changes: 70 additions & 8 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,71 @@ static zend_bool zend_get_unqualified_name(const zend_string *name, const char *
}
/* }}} */

struct _scalar_typehint_info {
const char* name;
const size_t name_len;
const zend_uchar type;
};

static const struct _scalar_typehint_info scalar_typehints[] = {
{"int", sizeof("int") - 1, IS_LONG},
{"integer", sizeof("integer") - 1, IS_LONG},
{"float", sizeof("float") - 1, IS_DOUBLE},
{"string", sizeof("string") - 1, IS_STRING},
{"bool", sizeof("bool") - 1, _IS_BOOL},
{"boolean", sizeof("boolean") - 1, _IS_BOOL},
{NULL, 0, IS_UNDEF}
};

static zend_always_inline const struct _scalar_typehint_info* zend_find_scalar_typehint(const zend_string *const_name) /* {{{ */
{
const struct _scalar_typehint_info *info = &scalar_typehints[0];
const char *uqname;
size_t uqname_len;

if (!zend_get_unqualified_name(const_name, &uqname, &uqname_len)) {
uqname = const_name->val;
uqname_len = const_name->len;
}

while (info->name) {
if (uqname_len == info->name_len && zend_binary_strcasecmp(uqname, uqname_len, info->name, info->name_len) == 0) {
break;
}
info++;
}

if (info->name) {
return info;
} else {
return NULL;
}
}
/* }}} */

ZEND_API void zend_assert_valid_class_name(const zend_string *const_name) /* {{{ */
{
const struct _scalar_typehint_info *info = zend_find_scalar_typehint(const_name);

if (info) {
zend_error_noreturn(E_COMPILE_ERROR, "\"%s\" cannot be used as a class name", info->name);
}
}
/* }}} */

static zend_always_inline zend_uchar zend_lookup_scalar_typehint_by_name(const zend_string *const_name) /* {{{ */
{
const struct _scalar_typehint_info *info = zend_find_scalar_typehint(const_name);

if (info) {
return info->type;
} else {
return 0;
}
}
/* }}} */


static void init_compiler_declarables(void) /* {{{ */
{
ZVAL_LONG(&CG(declarables).ticks, 0);
Expand Down Expand Up @@ -3962,15 +4027,12 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, zend_bool is_
}
} else {
zend_string *class_name = zend_ast_get_str(type_ast);
const struct _scalar_typehint_info *info = &scalar_typehints[0];
zend_uchar type;

while (info->name) {
if (class_name->len == info->name_len
&& zend_binary_strcasecmp(class_name->val, info->name_len, info->name, info->name_len) == 0) {
arg_info->type_hint = info->type;
goto done;
}
info++;
type = zend_lookup_scalar_typehint_by_name(class_name);
if (type != 0) {
arg_info->type_hint = type;
goto done;
}

if (zend_is_const_default_class_ref(type_ast)) {
Expand Down
41 changes: 2 additions & 39 deletions Zend/zend_compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,45 +31,6 @@

#include "zend_llist.h"

struct _scalar_typehint_info {
const char* name;
const size_t name_len;
const zend_uchar type;
};

static const struct _scalar_typehint_info scalar_typehints[] = {
{"int", sizeof("int") - 1, IS_LONG},
{"integer", sizeof("integer") - 1, IS_LONG},
{"float", sizeof("float") - 1, IS_DOUBLE},
{"string", sizeof("string") - 1, IS_STRING},
{"bool", sizeof("bool") - 1, _IS_BOOL},
{"boolean", sizeof("boolean") - 1, _IS_BOOL},
{NULL, 0, IS_UNDEF}
};

static zend_always_inline void zend_assert_valid_class_name(const zend_string *const_name)
{
const struct _scalar_typehint_info *info = &scalar_typehints[0];
const char *end_slash = strrchr(const_name->val, '\\');
zend_string *name = (zend_string*)const_name;

if (end_slash) {
end_slash++;
name = zend_string_init(end_slash, strlen(end_slash), 0);
}

while (info->name) {
if (name->len == info->name_len && zend_binary_strcasecmp(name->val, name->len, info->name, info->name_len) == 0) {
zend_error_noreturn(E_COMPILE_ERROR, "\"%s\" cannot be used as a class name", name->val);
}
info++;
}

if (end_slash) {
zend_string_release(name);
}
}

#define DEBUG_ZEND 0

#define SET_UNUSED(op) op ## _type = IS_UNUSED
Expand Down Expand Up @@ -777,6 +738,8 @@ int zendlex(zend_parser_stack_elem *elem);

int zend_add_literal(zend_op_array *op_array, zval *zv);

ZEND_API void zend_assert_valid_class_name(const zend_string *const_name);

/* BEGIN: OPCODES */

#include "zend_vm_opcodes.h"
Expand Down