+bool psi_impl_validate(struct psi_data *data, struct psi_impl *impl)
+{
+ if (!psi_impl_func_validate(data, impl->func)) {
+ return false;
+ }
+ if (!psi_return_stmt_validate(data, impl)) {
+ return false;
+ }
+ if (!psi_let_stmts_validate(data, impl)) {
+ return false;
+ }
+ if (!psi_set_stmts_validate(data, impl)) {
+ return false;
+ }
+ if (!psi_free_stmts_validate(data, impl)) {
+ return false;
+ }
+ return true;
+}
+
+size_t psi_impl_num_min_args(struct psi_impl *impl)
+{
+ size_t i;
+ struct psi_impl_arg *arg;
+
+ for (i = 0; psi_plist_get(impl->func->args, i, &arg); ++i) {
+ if (arg->def) {
+ break;
+ }
+ }
+ return i;
+}
+
+void psi_impl_stmt_free(struct psi_token ***abstract_stmt)
+{
+ switch ((**abstract_stmt)->type) {
+ case PSI_T_LET:
+ psi_let_stmt_free((void *) abstract_stmt);
+ break;
+ case PSI_T_SET:
+ psi_set_stmt_free((void *) abstract_stmt);
+ break;
+ case PSI_T_RETURN:
+ psi_return_stmt_free((void *) abstract_stmt);
+ break;
+ case PSI_T_FREE:
+ psi_free_stmt_free((void *) abstract_stmt);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+struct psi_let_stmt *psi_impl_get_let(struct psi_impl *impl,
+ struct psi_decl_var* var)
+{
+ size_t i = 0;
+ struct psi_let_stmt *let;
+
+ while (psi_plist_get(impl->stmts.let, i++, &let)) {
+ if (let->exp->var->arg == var->arg) {
+ return let;
+ }
+ }
+ return NULL;
+}
+
+struct psi_impl_arg *psi_impl_get_arg(struct psi_impl *impl,
+ struct psi_impl_var* var)
+{
+ size_t i = 0;
+ struct psi_impl_arg *iarg;
+
+ while (psi_plist_get(impl->func->args, i++, &iarg)) {
+ if (!strcmp(var->name, iarg->var->name)) {
+ return var->arg = iarg;
+ }
+ }
+ return NULL;
+}
+
+struct psi_decl_arg *psi_impl_get_temp_let_arg(struct psi_impl *impl,
+ struct psi_decl_var* var)
+{
+ size_t j = 0;
+ struct psi_let_stmt *let = NULL;
+
+ while (psi_plist_get(impl->stmts.let, j++, &let)) {
+ if (let->exp->kind != PSI_LET_TMP) {
+ continue;
+ }
+ if (strcmp(let->exp->var->name, var->name)) {
+ continue;
+ }
+ return var->arg = let->exp->var->arg;