Dear Nikolay, Many thanks for your efforts!
On Sat, Apr 6, 2019 at 2:29 PM Nikolay Shaplov <dh...@nataraj.su> wrote: > В письме от воскресенье, 24 февраля 2019 г. 14:31:55 MSK пользователь > Dmitry > Belyavsky написал: > > Hi! Am back here again. > > I've been thinking about this patch a while... Come to some conclusions > and > wrote some examples... > > First I came to idea that the best way to simplify the code is change the > state machine from if to switch/case. Because in your code a lot of > repetition > is done just because you can't say "Thats all, let's go to next symbol" in > any > place in the code. Now it should follow all the branches of if-else tree > that > is inside the state-machine "node" to get to the next symbol. > > To show how simpler the things would be I changed the state machine > processing > in lquery_in form if to switch/case, and changed the code for > LQPRS_WAITLEVEL > state processing, removing duplicate code, using "break" wherever it is > possible > > (The indention in this example is unproper to make diff more clear) > > so from that much of code > ================= > if (state == LQPRS_WAITLEVEL) > { > if (t_isspace(ptr)) > { > ptr += charlen; > pos++; > continue; > } > > escaped_count = 0; > real_levels++; > if (charlen == 1) > { > if (t_iseq(ptr, '!')) > { > GETVAR(curqlevel) = lptr = > (nodeitem *) > palloc0(sizeof(nodeitem) * numOR); > lptr->start = ptr + 1; > state = LQPRS_WAITDELIM; > curqlevel->numvar = 1; > curqlevel->flag |= LQL_NOT; > hasnot = true; > } > else if (t_iseq(ptr, '*')) > state = LQPRS_WAITOPEN; > else if (t_iseq(ptr, '\\')) > { > GETVAR(curqlevel) = lptr = > (nodeitem *) > palloc0(sizeof(nodeitem) * numOR); > lptr->start = ptr; > curqlevel->numvar = 1; > state = LQPRS_WAITESCAPED; > } > else if (strchr(".|@%{}", *ptr)) > { > UNCHAR; > } > else > { > GETVAR(curqlevel) = lptr = > (nodeitem *) > palloc0(sizeof(nodeitem) * numOR); > lptr->start = ptr; > state = LQPRS_WAITDELIM; > curqlevel->numvar = 1; > if (t_iseq(ptr, '"')) > { > lptr->flag |= > LVAR_QUOTEDPART; > } > } > } > else > { > GETVAR(curqlevel) = lptr = (nodeitem *) > palloc0(sizeof(nodeitem) * > numOR); > lptr->start = ptr; > state = LQPRS_WAITDELIM; > curqlevel->numvar = 1; > } > } > ===================== > I came to this > ===================== > case LQPRS_WAITLEVEL: > if (t_isspace(ptr)) > break; /* Just go to next symbol */ > escaped_count = 0; > real_levels++; > > if (charlen == 1) > { > if (strchr(".|@%{}", *ptr)) > UNCHAR; > if (t_iseq(ptr, '*')) > { > state = LQPRS_WAITOPEN; > break; > } > } > GETVAR(curqlevel) = lptr = (nodeitem *) > palloc0(sizeof(nodeitem) * > numOR); > lptr->start = ptr; > curqlevel->numvar = 1; > state = LQPRS_WAITDELIM; > if (charlen == 1) > { > if (t_iseq(ptr, '\\')) > { > state = LQPRS_WAITESCAPED; > break; > } > if (t_iseq(ptr, '!')) > { > lptr->start += 1 /*FIXME explain > why */; > curqlevel->flag |= LQL_NOT; > hasnot = true; > } > else if (t_iseq(ptr, '"')) > { > lptr->flag |= LVAR_QUOTEDPART; > } > } > break; > ======= > And this code is much more readable.... You can just read it aloud: > -Spaces we just skip > - on .|@%{} throws and exception > - for asterisk change state and nothing else > then for others allocate a buffer > - for slash we just set a flag > - for exclamation mark we set a flag and skip it > - for double quote set a flag. > > All the logic are clear. And in your version of the code it is difficult > to get > the idea from the code that simple. > > So my suggestion is following: > > 1. Submit and commit the patch that changes state machines from ifs to > switch/ > cases, and nothing else. This will reindent the code, so in order to keep > further changes visible, we should change nothing else. > > 2. Change your code to switch/cases, use break to deduplicate code > wherever is > possible, and commit it. > > I can join you while working with this (but then I am not sure I would be > able > to remain a reviewer...) > > I've also attached an example I've quoted above, formatted as a diff, so > it > would be easy to check how does it work. It should be applied after your > patch. > (I gave it a strange name ltree.not-a-patch hoping that commitfest > software > will not treat it a new version of a patch) I've applied your patch. >From my point of view, there is no major difference between case and chain if here. Neither case nor ifs allow extracting the common code to separate function - just because there seem to be no identical pieces of code. So yes, your patch makes sense, but I do not see any advantages of applying it. -- SY, Dmitry Belyavsky