[Info-vax] BASIC (and Horizon)

Lawrence D'Oliveiro ldo at nz.invalid
Wed Jan 31 18:21:34 EST 2024


On Wed, 31 Jan 2024 17:08:44 -0500, Arne Vajhøj wrote:

> On 1/31/2024 4:28 PM, Lawrence D'Oliveiro wrote:
>
>> I have never written a goto in C code (not production code, anyway). These
>> days, you need to do so much dynamic allocation, there is nearly always
>> some need for cleanup when exiting an inner block anyway, so you can’t
>> just jump directly somewhere else first. The overall pattern looks like
>> this:
>> 
>>      MyPtr obj = NULL;
>>      do /*once*/
>>        {
>>          ... possible other stuff ...
>>          «allocate memory for obj»;
>>          if («error occurred»)
>>              break;
>>          ... possible other stuff using obj ...
>>        }
>>      while (false);
>>      free(obj);
>> 
>> You can confirm, just by inspection, that there is no path out of the
>> block that does not pass through the free() call precisely once.
> 
> And the difference compared to:
> 
>       MyPtr obj = NULL;
>       ... possible other stuff ...
>       «allocate memory for obj»;
>       if («error occurred»)
>           goto lbl_freeobj;
>       ... possible other stuff using obj ...
>    lbl_freeobj:
>       free(obj);
> 
> are?

Nesting. Try to scale up to something like

static PyObject * discipline_makedict
  (
    PyObject * self,
    PyObject * args
  )
  {
    PyObject * result = NULL;
    PyObject * tempresult = NULL;
    br_PyObject * items;
    const br_char * msg = NULL;
    do /*once*/
      {
        const bool parsed_ok = PyArg_ParseTuple(args, "Os", &items, &msg);
        if (not parsed_ok)
            break;
        fprintf(stdout, "makedict says: “%s”\n", msg);
        if (not PyTuple_Check(items))
          {
            PyErr_SetString(PyExc_TypeError, "expecting a tuple");
            break;
          } /*if*/
        const ssize_t nr_items = PyTuple_Size(items);
        if (PyErr_Occurred())
            break;
        tempresult = PyDict_New();
        if (tempresult == NULL)
            break;
        for (ssize_t i = 0;;)
          {
            if (i == nr_items)
                break;
            br_PyObject * const item = PyTuple_GetItem(items, i);
            if (item == NULL)
                break;
            if (not PyTuple_Check(item) or PyTuple_Size(item) != 2)
              {
                PyErr_SetString(PyExc_TypeError, "expecting a 2-tuple");
                break;
              } /*if*/
            br_PyObject * const first = PyTuple_GetItem(item, 0);
            if (first == NULL)
                break;
            br_PyObject * const second = PyTuple_GetItem(item, 1);
            if (second == NULL)
                break;
            if (first == (PyObject *)&ExceptMe_type or second == (PyObject *)&ExceptMe_type)
              {
                PyErr_SetString(PyExc_ValueError, "ExceptMe object found");
                break;
              } /*if*/
            if (PyDict_SetItem(tempresult, first, second) < 0)
                break;
            ++i;
          } /*for*/
        if (PyErr_Occurred())
            break;
      /* all done */
        result = tempresult;
        tempresult = NULL; /* so I don’t dispose of it yet */
      }
    while (false);
    Py_XDECREF(tempresult);
    return
        result;
  } /*discipline_makedict*/

More details here
<https://gitlab.com/ldo/a_structured_discipline_of_programming/>.



More information about the Info-vax mailing list