basic callback support
authorMichael Wallner <mike@php.net>
Fri, 12 Feb 2016 13:32:14 +0000 (14:32 +0100)
committerMichael Wallner <mike@php.net>
Fri, 12 Feb 2016 13:32:14 +0000 (14:32 +0100)
TODO
src/context.c
src/context_validate.c
src/engine.c
src/libffi.c
src/marshal.c
src/marshal.h
src/parser.h
src/parser_proc.h
src/parser_proc.y

diff --git a/TODO b/TODO
index ee63abe58cf690118489fa11ee906b9ec94ee5c8..ffda07aae8dbe8c7289a913facdc78b3d176933b 100644 (file)
--- a/TODO
+++ b/TODO
@@ -6,3 +6,4 @@
 * pemalloc
 * unions
 * callbacks and function pointers
+* let impl_Var point to impl_arg, just like decl_var?
\ No newline at end of file
index ed26f8223214fb62c989e5ee8b57170a75771476..c86a595d8c79be86b07db026024c476080d3adcf 100644 (file)
@@ -342,6 +342,12 @@ void PSI_ContextDtor(PSI_Context *C)
                }
                free(C->structs);
        }
+       if (C->unions) {
+               if (C->unions->list) {
+                       free(C->unions->list);
+               }
+               free(C->unions);
+       }
        if (C->enums) {
                if (C->enums->list) {
                        free(C->enums->list);
index 56d7b2ea43eab6caad086c2cdd1dea03be010b09..87aba784064c7d3f1fd2a907940d6a482d9bdb49 100644 (file)
@@ -13,6 +13,7 @@
 #include "php_psi_macros.h"
 #include "php_psi_redirs.h"
 
+#include "parser.h"
 #include "calc.h"
 #include "marshal.h"
 #include "engine.h"
@@ -111,6 +112,22 @@ static inline int locate_decl_type_enum(decl_enums *enums, decl_type *type) {
        return 0;
 }
 
+static inline int locate_decl_type_decl(decls *decls, decl_type *type) {
+       size_t i;
+
+       if (type->func) {
+               return 1;
+       }
+       if (decls) for (i = 0; i < decls->count; ++i) {
+               if (!strcmp(decls->list[i]->func->var->name, type->name)) {
+                       type->func = decls->list[i];
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
 static inline int validate_decl_struct(PSI_Data *data, decl_struct *s);
 static inline int validate_decl_union(PSI_Data *data, decl_union *u);
 static inline int validate_decl_enum(PSI_Data *data, decl_enum *e);
@@ -143,6 +160,12 @@ static inline int validate_decl_type(PSI_Data *data, decl_type *type) {
                if (!locate_decl_type_enum(data->enums, type)) {
                        return 0;
                }
+               break;
+       case PSI_T_FUNCTION:
+               if (!locate_decl_type_decl(data->decls, type)) {
+                       return 0;
+               }
+               break;
        }
        return 1;
 }
@@ -781,7 +804,7 @@ static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg
                }
        }
 
-       if (ref_type->type == PSI_T_STRUCT) {
+       if (set->inner && ref_type->type == PSI_T_STRUCT) {
                /* to_array(struct, to_...) */
                if (!set->outer.set || set->outer.set->inner->vals != set->inner->vals) {
                        for (i = 0; i < set->inner->count; ++i) {
@@ -877,47 +900,60 @@ static inline int validate_impl_ret_stmt(PSI_Data *data, impl *impl) {
                return 0;
        }
 
-       impl->decl->impl = impl;
+       //impl->decl->impl = impl;
 
        return 1;
 }
 
-static inline int validate_let_func(PSI_Data *data, let_func *func, impl *impl) {
-       int check = 0;
-       size_t j;
+static inline impl_arg *locate_impl_var_arg(impl_var *var, impl_args *args) {
+       size_t i;
 
-       if (impl->func->args) {
-               for (j = 0; j < impl->func->args->count; ++j) {
-                       impl_arg *iarg = impl->func->args->args[j];
+       for (i = 0; i < args->count; ++i) {
+               impl_arg *iarg = args->args[i];
 
-                       if (!strcmp(func->var->name, iarg->var->name)) {
-                               func->arg = iarg;
-                               check = 1;
-                               break;
-                       }
+               if (!strcmp(var->name, iarg->var->name)) {
+                       return var->arg = iarg;
                }
        }
-       if (!check) {
-               data->error(data, func->var->token, PSI_WARNING, "Unknown value '$%s' of `let` statement"
-                               " for cast '%s' of implementation '%s'",
-                               func->var->name, func->name, impl->func->name);
-               return 0;
+
+       return NULL;
+}
+
+static inline int validate_let_func(PSI_Data *data, let_func *func, impl *impl) {
+       if (impl->func->args) {
+               if (!locate_impl_var_arg(func->var, impl->func->args)) {
+                       data->error(data, func->var->token, PSI_WARNING,
+                                       "Unknown variable '$%s' of `let` statement"
+                                       " for cast '%s' of implementation '%s'",
+                                       func->var->name, func->name, impl->func->name);
+                       return 0;
+               }
+       }
+       switch (func->type) {
+       case PSI_T_BOOLVAL:             func->handler = psi_let_boolval;        break;
+       case PSI_T_INTVAL:              func->handler = psi_let_intval;         break;
+       case PSI_T_FLOATVAL:    func->handler = psi_let_floatval;       break;
+       case PSI_T_STRVAL:              func->handler = psi_let_strval;         break;
+       case PSI_T_STRLEN:              func->handler = psi_let_strlen;         break;
+       case PSI_T_PATHVAL:             func->handler = psi_let_pathval;        break;
+       case PSI_T_ARRVAL:              func->handler = psi_let_arrval;         break;
+       case PSI_T_OBJVAL:              func->handler = psi_let_objval;         break;
+       EMPTY_SWITCH_DEFAULT_CASE();
        }
        return 1;
 }
 
-static inline int validate_let_callback(PSI_Data *data, decl_var *let_var, let_callback *cb, impl *impl) {
-       decl_type *cb_type;
-       decl *cb_func;
+static inline int validate_let_callback(PSI_Data *data, decl_var *cb_var, let_callback *cb, impl *impl) {
        size_t i;
+       decl *cb_func;
+       decl_type *cb_type = real_decl_type(cb_var->arg->type);
 
        if (!validate_let_func(data, cb->func, impl)) {
                return 0;
        }
 
-       cb_type = real_decl_type(let_var->arg->type);
        if (cb_type->type != PSI_T_FUNCTION) {
-               data->error(data, let_var->token, PSI_WARNING, "Not a function: %s", let_var->name);
+               data->error(data, cb_var->token, PSI_WARNING, "Not a function: %s", cb_var->name);
                return 0;
        }
        cb_func = cb_type->func;
@@ -926,6 +962,14 @@ static inline int validate_let_callback(PSI_Data *data, decl_var *let_var, let_c
                        return 0;
                }
        }
+
+       if (!validate_decl(data, NULL, cb_func)) {
+               return 0;
+       }
+
+       cb->decl = cb_func;
+
+       return 1;
 }
 
 static inline int validate_impl_let_stmts(PSI_Data *data, impl *impl) {
@@ -936,7 +980,6 @@ static inline int validate_impl_let_stmts(PSI_Data *data, impl *impl) {
        for (i = 0; i < impl->stmts->let.count; ++i) {
                let_stmt *let = impl->stmts->let.list[i];
                decl_var *let_var;
-               int check = 0;
 
                if (let->val && let->val->kind == PSI_LET_TMP) {
                        let_var = let->val->data.var;
index 51f3b2879e85783053010282c9b2bf1d080cfc2b..0c170cb63f5e4839e5cde371752bd8726bd7b4ab 100644 (file)
@@ -260,58 +260,18 @@ static inline void *psi_do_calloc(let_calloc *alloc)
 
 static inline impl_val *psi_let_val(token_t let_func, impl_arg *iarg, impl_val *arg_val, decl_struct *strct, void **to_free)
 {
-       switch (let_func) {
-       case PSI_T_BOOLVAL:
-               break;
-       case PSI_T_INTVAL:
-               break;
-       case PSI_T_FLOATVAL:
-               break;
-       case PSI_T_PATHVAL:
-       case PSI_T_STRVAL:
-               if (PSI_T_PATHVAL == let_func) {
-
-               }
-               break;
-       case PSI_T_STRLEN:
-               break;
-       case PSI_T_ARRVAL:
-               if (iarg->type->type == PSI_T_ARRAY) {
-                       arg_val = psi_array_to_struct(strct, HASH_OF(iarg->_zv));
-                       *to_free = arg_val;
-               }
-               break;
-       case PSI_T_OBJVAL:
-               if (iarg->type->type == PSI_T_OBJECT) {
-                       psi_object *obj;
-
-                       if (!instanceof_function(Z_OBJCE_P(iarg->_zv), psi_object_get_class_entry())) {
-                               return NULL;
-                       }
-
-                       obj = PSI_OBJ(iarg->_zv, NULL);
-                       arg_val->ptr = obj->data;
-               }
-               break;
-       case PSI_T_CALLBACK:
-               if (iarg->type->type == PSI_T_CALLABLE) {
-                       
-               }
-               break;
-       EMPTY_SWITCH_DEFAULT_CASE();
-       }
+       abort();
        return arg_val;
 }
 
 static inline impl_val *psi_let_func(let_func *func, decl_arg *darg) {
-       return darg->ptr = func->handler(darg->ptr, darg->type, func->arg, &darg->mem);
+       return darg->ptr = func->handler(darg->ptr, darg->type, func->var->arg, &darg->mem);
 }
 
 static inline void *psi_do_let(let_stmt *let)
 {
        decl_arg *darg = let->var->arg;
        impl_val *arg_val = darg->ptr;
-       impl_arg *iarg;
 
        switch (let->val ? let->val->kind : PSI_LET_NULL) {
        case PSI_LET_TMP:
@@ -335,7 +295,7 @@ static inline void *psi_do_let(let_stmt *let)
                darg->mem = arg_val->ptr;
                break;
        case PSI_LET_CALLBACK:
-               arg_val->ptr = 0 /* callback closure */;
+               arg_val->ptr = let->val->data.callback->decl->call.sym;
                break;
        case PSI_LET_NUMEXP:
                arg_val->zend.lval = psi_long_num_exp(let->val->data.num, NULL);
@@ -344,12 +304,7 @@ static inline void *psi_do_let(let_stmt *let)
                if (!psi_let_func(let->val->data.func, darg)) {
                        return NULL;
                }
-
-               iarg = let->val->data.func->arg;
-
-               if (!(darg->ptr = psi_let_val(let->val->data.func->type, iarg, darg->ptr, real_decl_type(darg->type)->strct, &darg->mem))) {
-                       return NULL;
-               }
+               break;
        }
 
        if (let->val && let->val->flags.one.is_reference) {
index 221e2c24507689b02549a5fd65f6a3551c853685..0e948a85257739e376f10ad28e3f0bb32d48ff1c 100644 (file)
@@ -78,49 +78,44 @@ static void psi_ffi_handler(ffi_cif *_sig, void *_result, void **_args, void *_d
 
 static void psi_ffi_callback(ffi_cif *_sig, void *_result, void **_args, void *_data)
 {
+       size_t i;
        unsigned argc = _sig->nargs;
        void **argv = _args;
-       ffi_arg *res = _result;
-       let_stmt *let;
-       decl_arg *darg = let->var->arg;
-       decl *decl_cb = darg->type->func;
-       let_callback *cb = let->val->data.callback;
-       impl_arg *iarg = cb->func->arg;
-       size_t i, argc = cb->args->count;
-       zval return_value, *argv = calloc(argc, sizeof(*argv));
-
-       // prepare args for the userland call
-       for (i = 0; i < decl_cb->args->count; ++i) {
+       let_callback *cb = _data;
+       decl *decl_cb = cb->decl;
+       impl_arg *iarg = cb->func->var->arg;
+       zval return_value, *zargv = calloc(argc, sizeof(*zargv));
+       void *result, *to_free = NULL;
+
+       ZEND_ASSERT(argc == cb->decl->args->count);
 
+       /* prepare args for the userland call */
+       for (i = 0; i < argc; ++i) {
+               cb->decl->args->args[i]->ptr = argv[i];
        }
        for (i = 0; i < cb->args->count; ++i) {
-               psi_do_set(&argv[i], cb->args->vals[i]);
+               psi_do_set(&zargv[i], cb->args->vals[i]);
        }
-       zend_fcall_info_argp(iarg->val.zend.cb->fci, argc, argv);
-       zend_fcall_info_call(&iarg->val.zend.cb->fci, &iarg->val.zend.cb->fcc,
-                       &return_value, NULL);
-       // marshal return value of the userland call
-       switch (cb->func->type) {
-       case PSI_T_BOOLVAL:
-               break;
-       case PSI_T_INTVAL:
-               break;
-       case PSI_T_FLOATVAL:
-               break;
-       case PSI_T_PATHVAL:
-       case PSI_T_STRVAL:
-               break;
-       case PSI_T_STRLEN:
-               break;
-       case PSI_T_ARRVAL:
-               break;
-       case PSI_T_OBJVAL:
-               break;
-       case PSI_T_CALLBACK:
-               break;
-       EMPTY_SWITCH_DEFAULT_CASE();
+       zend_fcall_info_argp(&iarg->val.zend.cb->fci, cb->args->count, zargv);
+
+       /* callback into userland */
+       ZVAL_UNDEF(&return_value);
+       iarg->_zv = &return_value;
+       zend_fcall_info_call(&iarg->val.zend.cb->fci, &iarg->val.zend.cb->fcc, iarg->_zv, NULL);
+
+       /* marshal return value of the userland call */
+       switch (iarg->type->type) {
+       case PSI_T_BOOL:        zend_parse_arg_bool(iarg->_zv, &iarg->val.zend.bval, NULL, 0);          break;
+       case PSI_T_LONG:        zend_parse_arg_long(iarg->_zv, &iarg->val.zend.lval, NULL, 0, 1);       break;
+       case PSI_T_FLOAT:
+       case PSI_T_DOUBLE:      zend_parse_arg_double(iarg->_zv, &iarg->val.dval, NULL, 0);                     break;
+       case PSI_T_STRING:      zend_parse_arg_str(iarg->_zv, &iarg->val.zend.str, 0);                          break;
+       }
+       result = cb->func->handler(_result, decl_cb->func->type, iarg, &to_free);
+
+       if (result != _result) {
+               *(void **)_result = result;
        }
-       darg->ptr = psi_let_val(cb->func->type, iarg, darg->ptr, real_decl_type(darg->type)->strct, &darg->mem);
 }
 
 static inline ffi_type *psi_ffi_decl_arg_type(decl_arg *darg);
@@ -163,12 +158,14 @@ static inline PSI_LibffiCall *PSI_LibffiCallAlloc(PSI_Context *C, decl *decl) {
        return call;
 }
 
-static inline void PSI_LibffiCallInitClosure(PSI_Context *C, PSI_LibffiCall *call, impl *impl) {
+static inline ffi_status PSI_LibffiCallInitClosure(PSI_Context *C, PSI_LibffiCall *call, impl *impl) {
        PSI_LibffiContext *context = C->context;
-       ffi_status rc;
 
-       rc = psi_ffi_prep_closure(&call->closure, &call->code, &context->signature, psi_ffi_handler, impl);
-       ZEND_ASSERT(FFI_OK == rc);
+       return psi_ffi_prep_closure(&call->closure, &call->code, &context->signature, psi_ffi_handler, impl);
+}
+
+static inline ffi_status PSI_LibffiCallInitCallbackClosure(PSI_Context *C, PSI_LibffiCall *call, let_callback *cb) {
+       return psi_ffi_prep_closure(&call->closure, &call->code, &call->signature, psi_ffi_callback, cb);
 }
 
 static inline void PSI_LibffiCallFree(PSI_LibffiCall *call) {
@@ -311,18 +308,6 @@ static inline ffi_type *psi_ffi_decl_type(decl_type *type) {
 
        switch (real->type) {
        case PSI_T_FUNCTION:
-               if (!real->func->call.sym) {
-                       PSI_LibffiCall *call = PSI_LibffiCallAlloc(&PSI_G(context), real->func);
-                       ffi_status rc;
-
-                       rc = psi_ffi_prep_closure(
-                                       (void *) &real->func->call.closure.data,
-                                       &real->func->call.sym, &call->signature, psi_ffi_handler, NULL);
-                       if (FFI_OK == rc) {
-                               real->func->call.info = call;
-                               real->func->call.closure.dtor = psi_ffi_closure_free;
-                       }
-               }
                return &ffi_type_pointer;
 
        case PSI_T_STRUCT:
@@ -394,7 +379,7 @@ static void psi_ffi_dtor(PSI_Context *C)
 
 static zend_function_entry *psi_ffi_compile(PSI_Context *C)
 {
-       size_t i, j = 0;
+       size_t c, i, j = 0;
        zend_function_entry *zfe;
 
        if (!C->impls) {
@@ -412,19 +397,41 @@ static zend_function_entry *psi_ffi_compile(PSI_Context *C)
                }
 
                call = PSI_LibffiCallAlloc(C, impl->decl);
-               PSI_LibffiCallInitClosure(C, call, impl);
+               if (FFI_OK != PSI_LibffiCallInitClosure(C, call, impl)) {
+                       PSI_LibffiCallFree(call);
+                       continue;
+               }
 
                zf->fname = impl->func->name + (impl->func->name[0] == '\\');
                zf->num_args = impl->func->args->count;
                zf->handler = call->code;
                zf->arg_info = psi_internal_arginfo(impl);
                ++j;
+
+               for (c = 0; c < impl->stmts->let.count; ++c) {
+                       let_stmt *let = impl->stmts->let.list[c];
+
+                       if (let->val->kind == PSI_LET_CALLBACK) {
+                               let_callback *cb = let->val->data.callback;
+
+                               call = PSI_LibffiCallAlloc(C, cb->decl);
+                               if (FFI_OK != PSI_LibffiCallInitCallbackClosure(C, call, cb)) {
+                                       PSI_LibffiCallFree(call);
+                                       continue;
+                               }
+
+                               cb->decl->call.sym = call->code;
+                       }
+               }
        }
 
        for (i = 0; i < C->decls->count; ++i) {
                decl *decl = C->decls->list[i];
 
-               if (decl->impl) {
+//             if (decl->impl) {
+//                     continue;
+//             }
+               if (decl->call.info) {
                        continue;
                }
 
index 23042a479163777ad65558e28a10d5d606c1528b..31ff9ba8f8f6fcafbafc4ffeaa36eb10cf2296d1 100644 (file)
@@ -88,7 +88,7 @@ void psi_to_int(zval *return_value, set_value *set, impl_val *ret_val)
 }
 
 static inline impl_val *psi_val_intval(impl_val *tmp, token_t real_type, zend_long intval) {
-       switch (real_decl_type(type)->type) {
+       switch (real_type) {
        case PSI_T_INT8:                tmp->i8 = intval;               break;
        case PSI_T_UINT8:               tmp->u8 = intval;               break;
        case PSI_T_INT16:               tmp->i16 = intval;              break;
@@ -148,7 +148,7 @@ void psi_to_double(zval *return_value, set_value *set, impl_val *ret_val)
 }
 
 static inline impl_val *psi_val_floatval(impl_val *tmp, token_t real_type, double floatval) {
-       switch (real_decl_type(type)->type) {
+       switch (real_type) {
        case PSI_T_INT8:                tmp->i8 = floatval;             break;
        case PSI_T_UINT8:               tmp->u8 = floatval;             break;
        case PSI_T_INT16:               tmp->i16 = floatval;    break;
@@ -171,7 +171,7 @@ static inline impl_val *psi_val_floatval(impl_val *tmp, token_t real_type, doubl
 impl_val *psi_let_floatval(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free)
 {
        double floatval;
-       token_t real_type = type ? real_decl_type(type)->real : PSI_T_DOUBLE;
+       token_t real_type = type ? real_decl_type(type)->type : PSI_T_DOUBLE;
 
        if (iarg->type->type == PSI_T_FLOAT || iarg->type->type == PSI_T_DOUBLE) {
                floatval = iarg->val.dval;
@@ -476,13 +476,25 @@ void psi_to_array(zval *return_value, set_value *set, impl_val *r_val)
        }
 }
 
-impl_val *psi_arrval(impl_val *tmp, decl_type *type, void *val, void **to_free)
+impl_val *psi_let_arrval(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free)
 {
-       HashTable *arr = (HashTable *) val;
-       decl_type *real = type ? real_decl_type(type) : NULL;
+       decl_type *real = real_decl_type(type);
+       HashTable *arr;
+
+       if (iarg->type->type != PSI_T_ARRAY) {
+               SEPARATE_ARG_IF_REF(iarg->_zv);
+               convert_to_array(iarg->_zv);
+       }
+       arr = HASH_OF(iarg->_zv);
 
-       ZEND_ASSERT(real && real->type == PSI_T_STRUCT);
-       return *to_free = psi_array_to_struct(real->strct, arr);
+       switch (real->type) {
+       case PSI_T_STRUCT:
+               *to_free = tmp = psi_array_to_struct(real->strct, arr);
+               break;
+       EMPTY_SWITCH_DEFAULT_CASE();
+       }
+
+       return tmp;
 }
 
 void psi_to_object(zval *return_value, set_value *set, impl_val *r_val)
@@ -500,16 +512,16 @@ void psi_to_object(zval *return_value, set_value *set, impl_val *r_val)
        }
 }
 
-impl_val *psi_objval(impl_val *tmp, decl_type *type, void *val, void **to_free)
+impl_val *psi_let_objval(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free)
 {
-       zval *zv = (zval *) val;
        psi_object *obj;
 
-       if (!instanceof_function(Z_OBJCE_P(zv), psi_object_get_class_entry())) {
+       if (Z_TYPE_P(iarg->_zv) != IS_OBJECT
+       ||      !instanceof_function(Z_OBJCE_P(iarg->_zv), psi_object_get_class_entry())) {
                return NULL;
        }
 
-       obj = PSI_OBJ(zv, NULL);
+       obj = PSI_OBJ(iarg->_zv, NULL);
        tmp->ptr = obj->data;
 
        return tmp;
index 6b2d7fad14f663367e3e3dd65831f5f255fde146..a6028dce5ca29824d78beadf27c0e3b8ee62f527 100644 (file)
@@ -13,4 +13,13 @@ void psi_to_object(zval *return_value, set_value *set, impl_val *ret_val);
 void *psi_array_to_struct(decl_struct *s, HashTable *arr);
 void psi_from_zval(impl_val *mem, decl_arg *spec, zval *zv, void **tmp);
 
+impl_val *psi_let_boolval(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free);
+impl_val *psi_let_intval(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free);
+impl_val *psi_let_floatval(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free);
+impl_val *psi_let_strval(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free);
+impl_val *psi_let_pathval(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free);
+impl_val *psi_let_strlen(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free);
+impl_val *psi_let_arrval(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free);
+impl_val *psi_let_objval(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free);
+
 #endif
index 30388ad7d3e7bea7a2ea4255b4fcf9b2dffd0552..0041155ce8827fac03035b92c5b18189dbf631e3 100644 (file)
@@ -157,7 +157,7 @@ typedef struct decl_arg {
        decl_type *type;
        decl_var *var;
        decl_struct_layout *layout;
-       struct let_stmt *let;
+       struct let_stmt *let; /* FIXME: decls must not point to impls !!! */
        impl_val val;
        void *ptr;
        void *mem;
@@ -297,10 +297,6 @@ typedef struct decl_callinfo {
        size_t argc;
        void **args;
        void **rval;
-       struct {
-               void *data;
-               void (*dtor)(void *data);
-       } closure;
 } decl_callinfo;
 
 typedef struct decl {
@@ -481,6 +477,7 @@ static inline void free_impl_type(impl_type *type) {
 typedef struct impl_var {
        PSI_Token *token;
        char *name;
+       struct impl_arg *arg;
        unsigned reference:1;
 } impl_var;
 
@@ -601,6 +598,7 @@ static inline impl_arg *init_impl_arg(impl_type *type, impl_var *var, impl_def_v
        impl_arg *arg = calloc(1, sizeof(*arg));
        arg->type = type;
        arg->var = var;
+       arg->var->arg = arg;
        arg->def = def;
        return arg;
 }
@@ -902,6 +900,7 @@ static inline void free_let_calloc(let_calloc *alloc) {
 typedef struct let_callback {
        struct let_func *func;
        struct set_values *args;
+       decl *decl;
 } let_callback;
 
 static inline void free_let_func(struct let_func *func);
@@ -924,8 +923,7 @@ typedef struct let_func {
        token_t type;
        char *name;
        impl_var *var;
-       impl_arg *arg;
-       impl_val *(*handler)(impl_val *tmp, decl_type *type, void *val, void **to_free);
+       impl_val *(*handler)(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free);
 } let_func;
 
 static inline let_func *init_let_func(token_t type, const char *name, impl_var *var) {
@@ -1088,9 +1086,10 @@ static inline set_value *init_set_value(set_func *func, decl_vars *vars) {
        val->vars = vars;
        return val;
 }
+
+static inline set_values *add_set_value(set_values *vals, set_value *val);
 static inline set_value *add_inner_set_value(set_value *val, set_value *inner) {
-       val->inner->vals = realloc(val->inner->vals, ++val->inner->count * sizeof(*val->inner->vals));
-       val->inner->vals[val->inner->count-1] = inner;
+       val->inner = add_set_value(val->inner, inner);
        inner->outer.set = val;
        return val;
 }
@@ -1103,11 +1102,7 @@ static inline void free_set_value(set_value *val) {
                free_decl_vars(val->vars);
        }
        if (val->inner && (!val->outer.set || val->outer.set->inner != val->inner)) {
-               size_t i;
-               for (i = 0; i < val->inner->count; ++i) {
-                       free_set_value(val->inner->vals[i]);
-               }
-               free(val->inner->vals);
+               free_set_values(val->inner);
        }
        if (val->num) {
                free_num_exp(val->num);
@@ -1126,6 +1121,9 @@ static inline set_values *init_set_values(set_value *val) {
 }
 
 static inline set_values *add_set_value(set_values *vals, set_value *val) {
+       if (!vals) {
+               vals = calloc(1, sizeof(*vals));
+       }
        vals->vals = realloc(vals->vals, ++vals->count * sizeof(val));
        vals->vals[vals->count-1] = val;
        return vals;
@@ -1133,6 +1131,11 @@ static inline set_values *add_set_value(set_values *vals, set_value *val) {
 
 static inline void free_set_values(set_values *vals) {
        if (vals->vals) {
+               size_t i;
+
+               for (i = 0; i < vals->count; ++i) {
+                       free_set_value(vals->vals[i]);
+               }
                free(vals->vals);
        }
        free(vals);
index 344fdb9a9fdf9ceae2eb50124a3593a9639a0817..d7f28a2e37ab3a6caf6ad9f7679d9c814d86b734 100644 (file)
@@ -9,60 +9,60 @@
 #define PSI_T_LET                              9
 #define PSI_T_RETURN                          10
 #define PSI_T_CALLOC                          11
-#define PSI_T_LIB                             12
-#define PSI_T_STRING                          13
-#define PSI_T_EOF                             14
-#define PSI_T_EOS                             15
-#define PSI_T_QUOTED_STRING                   16
-#define PSI_T_ENUM                            17
-#define PSI_T_LBRACE                          18
-#define PSI_T_RBRACE                          19
-#define PSI_T_COMMA                           20
-#define PSI_T_EQUALS                          21
-#define PSI_T_UNION                           22
-#define PSI_T_STRUCT                          23
-#define PSI_T_COLON                           24
-#define PSI_T_LPAREN                          25
-#define PSI_T_NUMBER                          26
-#define PSI_T_RPAREN                          27
-#define PSI_T_BOOL                            28
-#define PSI_T_INT                             29
-#define PSI_T_FLOAT                           30
-#define PSI_T_CONST                           31
-#define PSI_T_NSNAME                          32
-#define PSI_T_TYPEDEF                         33
-#define PSI_T_VOID                            34
-#define PSI_T_LBRACKET                        35
-#define PSI_T_RBRACKET                        36
-#define PSI_T_ELLIPSIS                        37
-#define PSI_T_CHAR                            38
-#define PSI_T_SHORT                           39
-#define PSI_T_LONG                            40
-#define PSI_T_DOUBLE                          41
-#define PSI_T_UNSIGNED                        42
-#define PSI_T_SIGNED                          43
-#define PSI_T_INT8                            44
-#define PSI_T_UINT8                           45
-#define PSI_T_INT16                           46
-#define PSI_T_UINT16                          47
-#define PSI_T_INT32                           48
-#define PSI_T_UINT32                          49
-#define PSI_T_INT64                           50
-#define PSI_T_UINT64                          51
-#define PSI_T_FUNCTION                        52
-#define PSI_T_NULL                            53
-#define PSI_T_TRUE                            54
-#define PSI_T_FALSE                           55
-#define PSI_T_DOLLAR_NAME                     56
-#define PSI_T_OBJVAL                          57
-#define PSI_T_ARRVAL                          58
-#define PSI_T_PATHVAL                         59
-#define PSI_T_STRLEN                          60
-#define PSI_T_STRVAL                          61
-#define PSI_T_FLOATVAL                        62
-#define PSI_T_INTVAL                          63
-#define PSI_T_BOOLVAL                         64
-#define PSI_T_CALLBACK                        65
+#define PSI_T_CALLBACK                        12
+#define PSI_T_LIB                             13
+#define PSI_T_STRING                          14
+#define PSI_T_EOF                             15
+#define PSI_T_EOS                             16
+#define PSI_T_QUOTED_STRING                   17
+#define PSI_T_ENUM                            18
+#define PSI_T_LBRACE                          19
+#define PSI_T_RBRACE                          20
+#define PSI_T_COMMA                           21
+#define PSI_T_EQUALS                          22
+#define PSI_T_UNION                           23
+#define PSI_T_STRUCT                          24
+#define PSI_T_COLON                           25
+#define PSI_T_LPAREN                          26
+#define PSI_T_NUMBER                          27
+#define PSI_T_RPAREN                          28
+#define PSI_T_BOOL                            29
+#define PSI_T_INT                             30
+#define PSI_T_FLOAT                           31
+#define PSI_T_CONST                           32
+#define PSI_T_NSNAME                          33
+#define PSI_T_TYPEDEF                         34
+#define PSI_T_VOID                            35
+#define PSI_T_LBRACKET                        36
+#define PSI_T_RBRACKET                        37
+#define PSI_T_ELLIPSIS                        38
+#define PSI_T_CHAR                            39
+#define PSI_T_SHORT                           40
+#define PSI_T_LONG                            41
+#define PSI_T_DOUBLE                          42
+#define PSI_T_UNSIGNED                        43
+#define PSI_T_SIGNED                          44
+#define PSI_T_INT8                            45
+#define PSI_T_UINT8                           46
+#define PSI_T_INT16                           47
+#define PSI_T_UINT16                          48
+#define PSI_T_INT32                           49
+#define PSI_T_UINT32                          50
+#define PSI_T_INT64                           51
+#define PSI_T_UINT64                          52
+#define PSI_T_FUNCTION                        53
+#define PSI_T_NULL                            54
+#define PSI_T_TRUE                            55
+#define PSI_T_FALSE                           56
+#define PSI_T_DOLLAR_NAME                     57
+#define PSI_T_OBJVAL                          58
+#define PSI_T_ARRVAL                          59
+#define PSI_T_PATHVAL                         60
+#define PSI_T_STRLEN                          61
+#define PSI_T_STRVAL                          62
+#define PSI_T_FLOATVAL                        63
+#define PSI_T_INTVAL                          64
+#define PSI_T_BOOLVAL                         65
 #define PSI_T_TO_OBJECT                       66
 #define PSI_T_TO_ARRAY                        67
 #define PSI_T_TO_STRING                       68
index 57fc968bab2b8226a8e7323cc0864ef3c83a0e26..50d54dab01a79b42e962ab5b9b1308578a816834 100644 (file)
@@ -29,7 +29,7 @@ void psi_error(int, const char *, int, const char *, ...);
 %nonassoc NAME.
 %left PLUS MINUS.
 %left SLASH ASTERISK.
-%fallback NAME TEMP FREE SET LET RETURN CALLOC LIB STRING.
+%fallback NAME TEMP FREE SET LET RETURN CALLOC CALLBACK LIB STRING.
 
 file ::= blocks.
 
@@ -716,7 +716,7 @@ let_func(func) ::= let_func_token(T) LPAREN impl_var(var) RPAREN. {
 %type callback_arg_list {set_values *}
 %destructor callback_arg_list {free_set_values($$);}
 callback_arg_list ::= .
-callback_arg_list(args) ::= COMMA callback_args(args_). {
+callback_arg_list(args) ::= callback_args(args_). {
        args = args_;
 }
 
@@ -743,7 +743,7 @@ let_val(val) ::= CALLOC LPAREN let_calloc(alloc) RPAREN. {
 let_val(val) ::= let_func(func). {
        val = init_let_val(PSI_LET_FUNC, func);
 }
-let_val(val) ::= CALLBACK let_func_token(F) LPAREN impl_var(var) callback_arg_list(args_) RPAREN. {
+let_val(val) ::= CALLBACK let_func_token(F) LPAREN impl_var(var) LPAREN callback_arg_list(args_) RPAREN RPAREN. {
        val = init_let_val(PSI_LET_CALLBACK, init_let_callback(
                init_let_func(F->type, F->text, var), args_));
        free(F);