X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=blobdiff_plain;f=src%2Ftypes%2Flet_callback.c;h=45639f82449dbded4f8c76252f6a796915ea9e9d;hp=632289f29c3f4a3b5a267cedae7e13c0fd1e8db3;hb=c9384515a81cb64d345b299908b2852f51bb8e6e;hpb=18ca609e4fa08a1c8fcdbb58e9aeb5fe55538b3c diff --git a/src/types/let_callback.c b/src/types/let_callback.c index 632289f..45639f8 100644 --- a/src/types/let_callback.c +++ b/src/types/let_callback.c @@ -27,11 +27,12 @@ #include "data.h" struct psi_let_callback *psi_let_callback_init(struct psi_let_func *func, - struct psi_plist *args) + struct psi_plist *args, struct psi_plist *cb_args) { struct psi_let_callback *cb = calloc(1, sizeof(*cb)); cb->func = func; cb->args = args; + cb->cb_args = cb_args; return cb; } @@ -43,6 +44,9 @@ void psi_let_callback_free(struct psi_let_callback **cb_ptr) *cb_ptr = NULL; psi_let_func_free(&cb->func); psi_plist_free(cb->args); + if (cb->cb_args) { + psi_plist_free(cb->cb_args); + } if (cb->token) { free(cb->token); } @@ -50,14 +54,38 @@ void psi_let_callback_free(struct psi_let_callback **cb_ptr) } } -bool psi_let_callback_validate(struct psi_data *data, struct psi_let_exp *exp, - struct psi_let_callback *cb, struct psi_impl *impl) + +static inline bool psi_let_callback_validate_decl_args(struct psi_data *data, + struct psi_let_callback *cb, struct psi_decl *cb_decl, + struct psi_impl *impl) +{ + size_t i; + struct psi_decl_var *call_arg; + + if (cb->cb_args) { + if (psi_plist_count(cb->cb_args) != psi_plist_count(cb_decl->args)) { + data->error(data, cb->token, PSI_WARNING, + "Argument count of callback statement of implementation '%s'" + "does not match argument count of callback declaration '%s'", + impl->func->name, cb_decl->func->var->name); + return false; + } + + for (i = 0; psi_plist_get(cb->cb_args, i, &call_arg); ++i) { + psi_plist_get(cb_decl->args, i, &call_arg->arg); + } + } + return true; +} + +bool psi_let_callback_validate(struct psi_data *data, struct psi_let_callback *cb, + struct psi_validate_scope *scope) { size_t i = 0; - struct psi_decl *cb_func; struct psi_decl_type *cb_type; + struct psi_let_exp *exp = scope->current_let; struct psi_decl_var *cb_var = exp->var; - struct psi_set_exp *set_exp; + struct psi_set_exp *set_exp, *parent_set = scope->current_set; cb_type = psi_decl_type_get_real(cb_var->arg->type); if (cb_type->type != PSI_T_FUNCTION) { @@ -66,19 +94,35 @@ bool psi_let_callback_validate(struct psi_data *data, struct psi_let_exp *exp, cb_var->name); return false; } - cb_func = cb_type->real.func; + cb->decl = cb_type->real.func; - while (psi_plist_get(cb->args, i++, &set_exp)) { - if (!psi_set_exp_validate(data, set_exp, impl, cb_func)) { - return false; - } + if (!psi_decl_validate_nodl(data, cb->decl, scope)) { + return false; } - - if (!psi_decl_validate_nodl(data, cb_func, NULL /* FIXME type_stack */)) { + if (!psi_let_callback_validate_decl_args(data, cb, cb->decl, scope->impl)) { return false; } + while (psi_plist_get(cb->args, i++, &set_exp)) { + if (cb->cb_args) { + struct psi_decl_var *cb_var; + + if (psi_plist_get(cb->cb_args, i - 1, &cb_var)) { + struct psi_decl_var *dvar = psi_set_exp_get_decl_var(set_exp); + dvar->arg = cb_var->arg; + } + } - cb->decl = cb_func; + scope->current_set = set_exp; + scope->cb_decl = cb->decl; + + if (!psi_set_exp_validate(data, set_exp, scope)) { + scope->cb_decl = NULL; + scope->current_set = parent_set; + return false; + } + scope->cb_decl = NULL; + scope->current_set = parent_set; + } return true; } @@ -86,7 +130,19 @@ bool psi_let_callback_validate(struct psi_data *data, struct psi_let_exp *exp, void psi_let_callback_dump(int fd, struct psi_let_callback *callback, unsigned level) { - dprintf(fd, "callback %s(%s(", + dprintf(fd, "callback("); + if (callback->cb_args) { + size_t i = 0; + struct psi_decl_var *cb_arg; + + while (psi_plist_get(callback->cb_args, i++, &cb_arg)) { + if (i > 1) { + dprintf(fd, ", "); + } + psi_decl_var_dump(fd, cb_arg); + } + } + dprintf(fd, ") as %s(%s(", callback->func->name, callback->func->var->name);