#include <assert.h>
-struct psi_let_func *psi_let_func_init(token_t type, const char *name,
+struct psi_let_func *psi_let_func_init(token_t type, zend_string *name,
struct psi_impl_var *var)
{
- struct psi_let_func *func = calloc(1, sizeof(*func));
+ struct psi_let_func *func = pecalloc(1, sizeof(*func), 1);
func->type = type;
- func->name = strdup(name);
+ func->name = zend_string_copy(name);
func->var = var;
return func;
}
struct psi_let_func *func = *func_ptr;
*func_ptr = NULL;
- if (func->token) {
- free(func->token);
- }
+ psi_token_free(&func->token);
psi_impl_var_free(&func->var);
- free(func->name);
+ zend_string_release(func->name);
if (func->inner) {
psi_plist_free(func->inner);
}
void psi_let_func_dump(int fd, struct psi_let_func *func, unsigned level)
{
- dprintf(fd, "%s(%s\t/* fqn=%s */", func->name, func->var->name, func->var->fqn);
+ dprintf(fd, "%s(%s\t/* fqn=%s */", func->name->val, func->var->name->val,
+ func->var->fqn->val);
if (func->inner) {
size_t i = 0, count = psi_plist_count(func->inner);
}
static inline int validate_let_func_type(struct psi_data *data,
- struct psi_let_func *func, struct psi_impl *impl)
+ struct psi_let_func *func, struct psi_validate_scope *scope)
{
switch (func->type) {
case PSI_T_BOOLVAL:
default:
data->error(data, func->var->token, PSI_WARNING,
"Unknown `let` cast function '%s' of implementation '%s'",
- func->name, impl->func->name);
+ func->name->val, scope->impl->func->name->val);
return false;
}
}
static inline bool validate_let_func_inner(struct psi_data *data,
- struct psi_let_exp *exp, struct psi_let_func *func,
- struct psi_impl *impl)
+ struct psi_let_func *func, struct psi_validate_scope *scope)
{
+ struct psi_let_exp *exp = scope->current_let;
+
if (func->inner) {
struct psi_decl_var *let_var = psi_let_exp_get_decl_var(exp);
struct psi_decl_type *var_typ;
struct psi_let_exp *inner;
while (psi_plist_get(func->inner, i++, &inner)) {
- const char *name = psi_let_exp_get_decl_var_name(inner);
+ zend_string *name = psi_let_exp_get_decl_var_name(inner);
struct psi_decl_arg *sub_arg;
inner->outer = exp;
if (name) {
sub_arg = psi_decl_arg_get_by_name(sub_args, name);
+ zend_string_release(name);
}
if (!name || !sub_arg) {
/* remove expr for portability with different struct members */
psi_plist_del(func->inner, --i, NULL);
psi_let_exp_free(&inner);
- } else if (!psi_let_exp_validate(data, inner, impl)) {
- return false;
+ } else {
+ scope->current_let = inner;
+ if (!psi_let_exp_validate(data, inner, scope)) {
+ scope->current_let = exp;
+ return false;
+ }
+ scope->current_let = exp;
}
}
} else if (func->type == PSI_T_ARRVAL
sub_var = psi_let_exp_get_impl_var(exp);
sub_ref = psi_let_exp_get_impl_var(inner);
- if (strcmp(sub_var->name, sub_ref->name)) {
+ if (!zend_string_equals(sub_var->name, sub_ref->name)) {
data->error(data, sub_var->token, E_WARNING,
"Inner `set` statement casts on pointers must"
" reference the same variable");
return false;
}
- if (!psi_let_exp_validate(data, inner, impl)) {
+ scope->current_let = inner;
+ if (!psi_let_exp_validate(data, inner, scope)) {
+ scope->current_let = exp;
return false;
}
+ scope->current_let = exp;
} else {
data->error(data, let_var->token, PSI_WARNING,
"Inner let statement's values must refer to a structure or"
" array type, got '%s%s' for '%s'", var_typ->name,
psi_t_indirection(let_var->arg->var->pointer_level),
- let_var->name);
+ let_var->name->val);
return false;
}
return true;
}
-bool psi_let_func_validate(struct psi_data *data, struct psi_let_exp *val,
- struct psi_let_func *func, struct psi_impl *impl)
+bool psi_let_func_validate(struct psi_data *data, struct psi_let_func *func,
+ struct psi_validate_scope *scope)
{
- if (impl->func->args) {
+ if (scope->impl->func->args) {
/* FIXME, func->var does not need to be referring to a func arg */
- psi_impl_get_arg(impl, func->var);
+ psi_impl_get_arg(scope->impl, func->var);
}
- if (!psi_impl_var_validate(data, func->var, impl, val, NULL)) {
+ if (!psi_impl_var_validate(data, func->var, scope)) {
return false;
}
- if (!validate_let_func_type(data, func, impl)) {
+ if (!validate_let_func_type(data, func, scope)) {
return false;
}
- if (!validate_let_func_inner(data, val, func, impl)) {
+ if (!validate_let_func_inner(data, func, scope)) {
return false;
}
return 1;
* we only want to set supplied data on unions
*/
if (!zend_symtable_str_exists(Z_ARRVAL_P(frame_arg->zval_ptr),
- &inner_var->name[1], strlen(&inner_var->name[1]))) {
+ &inner_var->name->val[1], inner_var->name->len - 1)) {
return;
}
}
/* example from dm_store/dbm_fetch with arrval($string) conversion:
let key = arrval($key,
- dptr = strval($0),
- dsize = strlen($0)
+ dptr = strval($0),
+ dsize = strlen($0)
);
# ---
darg = key
struct psi_let_exp *inner_let_exp, void *container,
struct psi_call_frame *frame)
{
- zval *zval_ptr;
+ zval *zval_ptr = NULL;
psi_marshal_let let_fn;
size_t i = 0, size;
struct psi_decl_var *dvar;
if (frame_arg->zval_ptr) {
while (psi_plist_get(func->inner, i++, &inner)) {
- darg_member = psi_decl_arg_get_by_name(darg_members,
- psi_let_exp_get_decl_var_name(inner));
+ zend_string *var_name = psi_let_exp_get_decl_var_name(inner);
+ darg_member = psi_decl_arg_get_by_name(darg_members, var_name);
exec_let_func_arrval_inner(func, darg, darg_member, frame_arg,
inner, container, frame);
+ zend_string_release(var_name);
}
}
} else if (func->inner) {