X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=src%2Ftypes%2Ffree_exp.c;fp=src%2Ftypes%2Ffree_exp.c;h=19c7a60abf60e499d146168de2265e57008e2aba;hb=9bcb1df0786a8193d65949c857baaba2f4296e84;hp=0000000000000000000000000000000000000000;hpb=5e240548ba570610ce0dbc248a2b7654a0e080fa;p=m6w6%2Fext-psi diff --git a/src/types/free_exp.c b/src/types/free_exp.c new file mode 100644 index 0000000..19c7a60 --- /dev/null +++ b/src/types/free_exp.c @@ -0,0 +1,142 @@ +/******************************************************************************* + Copyright (c) 2016, Michael Wallner . + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ + +#include "php_psi_stdinc.h" +#include "data.h" +#include "call.h" + +struct psi_free_exp *psi_free_exp_init(const char *func, struct psi_plist *vars) +{ + struct psi_free_exp *f = calloc(1, sizeof(*f)); + f->func = strdup(func); + f->vars = vars; + return f; +} + +void psi_free_exp_free(struct psi_free_exp **f_ptr) +{ + if (*f_ptr) { + struct psi_free_exp *f = *f_ptr; + + *f_ptr = NULL; + if (f->token) { + free(f->token); + } + free(f->func); + psi_plist_free(f->vars); + if (f->let) { + free(f->let); + } + free(f); + } +} + +void psi_free_exp_dump(int fd, struct psi_free_exp *call) +{ + size_t l = 0, c = psi_plist_count(call->vars); + struct psi_decl_var *fvar; + + dprintf(fd, "%s(", call->func); + while (psi_plist_get(call->vars, l++, &fvar)) { + psi_decl_var_dump(fd, fvar); + if (l < c) { + dprintf(fd, ", "); + } + } + dprintf(fd, ")"); +} + +static inline struct psi_decl *locate_free_decl(struct psi_plist *decls, + struct psi_free_exp *f) +{ + if (decls) { + size_t i = 0; + struct psi_decl *decl; + + while (psi_plist_get(decls, i++, &decl)) { + if (!strcmp(decl->func->var->name, f->func)) { + return f->decl = decl; + } + } + } + + return NULL; +} + +bool psi_free_exp_validate(struct psi_data *data, struct psi_free_exp *exp, + struct psi_impl *impl) +{ + size_t i; + struct psi_decl_var *free_var; + + /* first find the decl of the free func */ + if (!locate_free_decl(data->decls, exp)) { + data->error(data, exp->token, PSI_WARNING, + "Missing declaration '%s' in `free` statement" + " of implementation '%s'", exp->func, impl->func->name); + return false; + } + + /* now check for known vars */ + exp->let = calloc(psi_plist_count(exp->vars), sizeof(*exp->let)); + for (i = 0; psi_plist_get(exp->vars, i, &free_var); ++i) { + if (!psi_decl_arg_get_by_var(free_var, impl->decl->args, + impl->decl->func)) { + data->error(data, free_var->token, PSI_WARNING, + "Unknown variable '%s' of `free` statement" + " of implementation '%s'", + free_var->name, impl->func->name); + return false; + } + + exp->let[i] = psi_impl_get_let(impl, free_var); + assert(exp->let[i]); + } + + return true; +} + +void psi_free_exp_exec(struct psi_free_exp *f, struct psi_call_frame *frame) +{ + size_t i; + void **args; + struct psi_decl_var *dvar; + struct psi_call_frame *free_call; + + free_call = psi_call_frame_init(frame->context, f->decl, NULL); + psi_call_frame_enter(free_call); + + args = psi_call_frame_get_arg_pointers(free_call); + for (i = 0; psi_plist_get(f->vars, i, &dvar); ++i) { + struct psi_call_frame_symbol *frame_sym; + struct psi_let_exp *let = f->let[i]->exp; + + frame_sym = psi_call_frame_fetch_symbol(frame, let->var); + args[i] = deref_impl_val(frame_sym->ptr, dvar); + } + + psi_call_frame_do_call(free_call); + psi_call_frame_free(free_call); +}