void ft_pwd(char *line) { char **buf; int i; i = -1; if (!(buf = ft_strsplim(line))) return ; while (buf[++i]) buf[i] = (char *)c_call("ft_strtrim", buf[i]); if (buf[1] != '\0') { ft_putendl_fd("pwd: too many arguments", 2); ft_free_char2(buf); return ; } if (!(buf[0] = ft_strnew(2000))) return ; ft_putendl(getcwd(buf[0], 2000)); ft_free_char2(buf); }
static int lazy_rec_eval(CLazyLinker * self, Py_ssize_t var_idx, PyObject*one, PyObject*zero) { PyObject *rval = NULL; int verbose = 0; int err = 0; if (verbose) fprintf(stderr, "lazy_rec computing %i\n", (int)var_idx); if (self->var_computed[var_idx] || !self->var_has_owner[var_idx]) return 0; Py_ssize_t owner_idx = self->var_owner[var_idx]; // STEP 1: compute the pre-requirements of the node // Includes input nodes for non-lazy ops. for (int i = 0; i < self->node_n_prereqs[owner_idx]; ++i) { Py_ssize_t prereq_idx = self->node_prereqs[owner_idx][i]; if (!self->var_computed[prereq_idx]) { err = lazy_rec_eval(self, prereq_idx, one, zero); if (err) return err; } assert (self->var_computed[prereq_idx]); } // STEP 2: compute the node itself if (self->is_lazy[owner_idx]) { // update the compute_map cells corresponding to the inputs of this thunk for (int i = 0; i < self->node_n_inputs[owner_idx]; ++i) { int in_idx = self->node_inputs[owner_idx][i]; if (self->var_computed[in_idx]) { Py_INCREF(one); err = PyList_SetItem(self->var_computed_cells[in_idx], 0, one); } else { Py_INCREF(zero); err = PyList_SetItem(self->var_computed_cells[in_idx], 0, zero); } if (err) goto fail; } rval = pycall(self, owner_idx, verbose); // refcounting - rval is new ref //TODO: to prevent infinite loops // - consider check that a thunk does not ask for an input that is already computed if (rval == NULL) { assert (PyErr_Occurred()); err = 1; goto fail; } //update the computed-ness of any output cells for (int i = 0; i < self->node_n_outputs[owner_idx]; ++i) { int out_idx = self->node_outputs[owner_idx][i]; PyObject * el_i = PyList_GetItem(self->var_computed_cells[out_idx], 0); Py_ssize_t N = PyNumber_AsSsize_t(el_i, PyExc_IndexError); if (PyErr_Occurred()) { err = -1; goto pyfail; } assert (N==0 || N==1); self->var_computed[out_idx] = N; } if (!self->var_computed[var_idx]) { /* * If self is not computed after the call, this means that some * inputs are needed. Compute the ones on the returned list * and try to compute the current node again (with recursive call). * This allows a node to request more nodes more than once before * finally yielding a result. */ if (!PyList_Check(rval)) { //TODO: More helpful error to help find *which node* made this // bad thunk PyErr_SetString(PyExc_TypeError, "lazy thunk should return a list"); err = 1; goto pyfail; } if (!PyList_Size(rval)) { PyErr_SetString(PyExc_ValueError, "lazy thunk returned empty list without computing output"); err = 1; goto pyfail; } for (int i = 0; i < PyList_Size(rval); ++i) { PyObject * el_i = PyList_GetItem(rval, i); Py_ssize_t N = PyNumber_AsSsize_t(el_i, PyExc_IndexError); if (PyErr_Occurred()) { err = 1; goto pyfail; } assert (N <= self->node_n_inputs[owner_idx]); Py_ssize_t input_idx = self->node_inputs[owner_idx][N]; err = lazy_rec_eval(self, input_idx, one, zero); if (err) goto pyfail; } Py_DECREF(rval); /* * We intentionally skip all the end-of-function processing * (mark outputs, GC) as it will be performed by the call * that actually manages to compute the result. */ return lazy_rec_eval(self, var_idx, one, zero); } Py_DECREF(rval); } else //owner is not a lazy op. Ensure all intputs are evaluated. { // loop over inputs to owner // call lazy_rec_eval on each one that is not computed. // if there's an error, pass it up the stack for (int i = 0; i < self->node_n_inputs[owner_idx]; ++i) { Py_ssize_t input_idx = self->node_inputs[owner_idx][i]; if (!self->var_computed[input_idx]) { err = lazy_rec_eval(self, input_idx, one, zero); if (err) return err; } assert (self->var_computed[input_idx]); } // call the thunk for this owner. if (self->thunk_cptr_fn[owner_idx]) { err = c_call(self, owner_idx, verbose); if (err) goto fail; } else { rval = pycall(self, owner_idx, verbose); //rval is new ref if (rval) //pycall returned normally (no exception) { if (rval == Py_None) { Py_DECREF(rval); //ignore a return of None } else if (PyList_Check(rval)) { PyErr_SetString(PyExc_TypeError, "non-lazy thunk should return None, not list"); err = 1; goto pyfail; } else // don't know what it returned, but it wasn't right. { PyErr_SetObject(PyExc_TypeError, rval); err = 1; // We don't release rval since we put it in the error above goto fail; } } else // pycall returned NULL (internal error) { err = 1; goto fail; } } } // loop over all outputs and mark them as computed for (int i = 0; i < self->node_n_outputs[owner_idx]; ++i) { self->var_computed[self->node_outputs[owner_idx][i]] = 1; } // Free vars that are not needed anymore if (self->allow_gc) { for (int i = 0; i < self->node_n_inputs[owner_idx]; ++i) { int cleanup = 1; Py_ssize_t i_idx = self->node_inputs[owner_idx][i]; if (!self->var_has_owner[i_idx]) continue; for (int j = 0; j < self->n_output_vars; ++j) { if (i_idx == self->output_vars[j]) { cleanup = 0; break; } } if (!cleanup) continue; for (int j = 0; j < self->n_dependencies[i_idx]; ++j) { if (!self->var_computed[self->dependencies[i_idx][j]]) { cleanup = 0; break; } } if (!cleanup) continue; Py_INCREF(Py_None); err = PyList_SetItem(self->var_value_cells[i_idx], 0, Py_None); //See the Stack gc implementation for why we change it to 2 and not 0. self->var_computed[i_idx] = 2; if (err) goto fail; } } return 0; pyfail: Py_DECREF(rval); fail: set_position_of_error(self, owner_idx); return err; }
int main(void) { F f{}; c_call(f.get_ptr()); }
int main(void) { F f{}; c_call(&(f.get_int())); }