#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;
}
*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);
}
}
}
-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) {
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;
}
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);