+static inline int validate_let_val(struct psi_data *data, let_val *val, decl_var *let_var, impl *impl) {
+
+ switch (val->kind) {
+ case PSI_LET_NULL:
+ break;
+ case PSI_LET_TMP:
+ if (!let_var) {
+ data->error(data, NULL, PSI_WARNING,
+ "Ivalid let statement value of implementation '%s'",
+ impl->func->name);
+ return 0;
+ }
+ /* e.g. let bar = &strval($bar); // decl_arg(char **bar) */
+ /* e.g. let foo = *bar; */
+ let_var->pointer_level = val->data.var->pointer_level;
+ let_var->arg = init_decl_arg(
+ init_decl_type(
+ real_decl_type(val->data.var->arg->type)->type,
+ real_decl_type(val->data.var->arg->type)->name),
+ init_decl_var(
+ let_var->name,
+ let_var->pointer_level,
+ let_var->array_size));
+ break;
+ case PSI_LET_NUMEXP:
+ if (!validate_num_exp(data, val->data.num, impl->decl->args, impl->decl->func, NULL)) {
+ return 0;
+ }
+ break;
+ case PSI_LET_CALLOC:
+ if (!validate_num_exp(data, val->data.alloc->nmemb, impl->decl->args, impl->decl->func, NULL)) {
+ return 0;
+ }
+ if (!validate_num_exp(data, val->data.alloc->size, impl->decl->args, impl->decl->func, NULL)) {
+ return 0;
+ }
+ break;
+ case PSI_LET_CALLBACK:
+ if (!let_var) {
+ data->error(data, NULL, PSI_WARNING,
+ "Ivalid let statement value of implementation '%s'",
+ impl->func->name);
+ return 0;
+ }
+ if (val->data.callback->func->inner) {
+ size_t i;
+ decl_type *var_typ = real_decl_type(let_var->arg->type);
+ decl_args *sub_args;
+
+ switch (var_typ->type) {
+ case PSI_T_STRUCT:
+ sub_args = var_typ->real.strct->args;
+ break;
+ case PSI_T_UNION:
+ sub_args = var_typ->real.unn->args;
+ break;
+ default:
+ data->error(data, let_var->token, PSI_WARNING,
+ "Inner let statement's values must refer to a structure type, got '%s' for '%s'",
+ real_decl_type(let_var->arg->type)->name, let_var->name);
+ return 0;
+ }
+ for (i = 0; i < val->data.callback->func->inner->count; ++i) {
+ let_val *inner = val->data.callback->func->inner->vals[i];
+ switch (inner->kind) {
+ case PSI_LET_FUNC:
+ inner->data.func->outer = val;
+ inner->data.func->ref = locate_decl_arg(sub_args,
+ &inner->data.func->var->name[1]);
+ break;
+
+ break;
+ case PSI_LET_CALLBACK:
+ inner->data.callback->func->outer = val;
+ inner->data.callback->func->ref = locate_decl_arg(sub_args,
+ &inner->data.callback->func->var->name[1]);
+ break;
+ }
+ }
+ }
+ if (!validate_let_callback(data, let_var, val->data.callback, impl)) {
+ return 0;
+ }
+ break;
+ case PSI_LET_FUNC:
+ if (val->data.func->inner) {
+ size_t i;
+ decl_type *var_typ = real_decl_type(let_var->arg->type);
+ decl_args *sub_args;
+
+ switch (var_typ->type) {
+ case PSI_T_STRUCT:
+ sub_args = var_typ->real.strct->args;
+ break;
+ case PSI_T_UNION:
+ sub_args = var_typ->real.unn->args;
+ break;
+ default:
+ data->error(data, let_var->token, PSI_WARNING,
+ "Inner let statement's values must refer to a structure type, got '%s' for '%s'",
+ real_decl_type(let_var->arg->type)->name, let_var->name);
+ return 0;
+ }
+ for (i = 0; i < val->data.func->inner->count; ++i) {
+ let_val *inner = val->data.func->inner->vals[i];
+ switch (inner->kind) {
+ case PSI_LET_FUNC:
+ inner->data.func->outer = val;
+ inner->data.func->ref = locate_decl_arg(sub_args,
+ &inner->data.func->var->name[1]);
+ break;
+ case PSI_LET_CALLBACK:
+ inner->data.callback->func->outer = val;
+ inner->data.callback->func->ref = locate_decl_arg(sub_args,
+ &inner->data.callback->func->var->name[1]);
+ break;
+ }
+ }
+ }
+
+ val->data.func->var;
+
+ if (!validate_let_func(data, val->data.func, let_var, impl)) {
+ return 0;
+ }
+ break;
+ }
+
+ return 1;
+}
+
+static inline int validate_impl_let_stmts(struct psi_data *data, impl *impl) {