what is one entry and one exit of a simple construct? - c

I am reading some C text at the address https://cs.senecac.on.ca/~btp100/pages/content/const.html.
In the section "STRUCTURED PROGRAMMING", the author mentioned: "Structured programs are understandable, testable and readily modifiable. They consist of simple constructs, each of which has one entry point and one exit point."
I understood what is a structured program, but I am not really understanding the idea "one entry point and one exit point". What if we do not have such stuff?
Can anyone elaborate on that, please?

Look at the Flags example close to the bottom and Avoiding Jumps below that: https://cs.senecac.on.ca/~btp100/pages/content/const.html#fla
What they're basically trying to say here is that you could have some sort of loop (for/while/whatever) where you could use something like break to exit a loop prematurely, rather than waiting on the actual condition that you're checking in the loop to become false and have the loop exit normally. In this case you would have two exit points.
They suggest the use of a flag variable added to the loop's condition to have a single exit point, makes sense.
The use of continue is another example where you can "break structure." You could use continue to stop the current iteration of the loop and reenter it, where in this case you would have multiple entry points.
Things like that can make code a lot harder to read and be able to follow the flow, even though sometimes it may seem necessary to do so.

Related

What do "single-entry" and "single-exit" mean for a statement?

From An Integrated Approach to Software Engineering
By Pankaj Jalote
Clearly, no meaningful program can be written as a sequence of simple
statements without any branching or repetition (which also involves
branching). So, how is the objective of linearizing the control flow
to be achieved? By making use of structured constructs. In
structured programming, a statement is not a simple assignment
statement, it is a structured statement. The key property of a
structured statement is that it has a single-entry and a
single-exit. That is, during execution, the execution of the (structured) statement starts from one defined point and the execution
terminates at one defined point. With single-entry and single-exit
statements, we can view a program as a sequence of (structured)
statements. And if all statements are structured statements, then
during execution, the sequence of execution of these statements will
be the same as the sequence in the program text. Hence, by using
single-entry and single-exit statements, the correspondence between
the static and dynamic structures can be obtained.
The most commonly used single-entry and single-exit statements are
Selection: if B then S1 else S2
if B then S1
Iteration: While B do S
repeat S until B
Sequencing: S1; S2; S3;...
What do "single-entry" and "single-exit" mean in a structured statement?
Why are statements listed at the end are single-entry and single-exit?
For example, in if B then S1 else S2, why is it single exit, given it can terminates at either S1 or S2?
Can you give a statement which is not single entry?
Can you given a statement which is not single exit?
In many languages, the only statements that do not have a single entry are those which happen to contain labels for use with goto or switch statements located outside them, and the only statements that do not have a single exit are those which contain a goto to an outside location, trigger an exception, or otherwise force stack unwinding. Note that for any particular call of a function, the only "normal" exit point will be the code immediately following that call.
The notion of single entry/single exit may be unclear to those who have never worked with code that didn't use such an approach. Examples of the latter may be found when writing code for the platforms like the Atari 2600 where RAM space is often at an absolute premium. If a piece of code will be invoked from the code that shows the title screen, or from within the game logic, and there one can't afford the two bytes of stack space necessary for a subroutine-call instruction, it would not be uncommon to jump to the code (rather than using a "JSR" [jump to subroutine] instruction), and have the code exit by checking whether a game is in progress and jumping back to the appropriate spot in the "show title screen" or "perform game logic" code. Such a design may be awkward to maintain if it becomes necessary to invoke it from more places in the code, but such techniques may be necessary if RAM is really tight (e.g. one only has 128 bytes total, as on the Atari 2600).

Linux's continue statement

I often see Linux code with something like this
if (condition1)
continue;
.....
Now that doesn't make much sense, if condition1 it will continue to next line of code. If not condition1 it still fall through to next line of code. it doesn't have an alternative place to go if condition1 is not met.
any ideas?
The continue statement does not mean to continue on the next line. It causes the remaining portion of the enclosing for, while or do-while loop body to be skipped.
Refer to cppreference (or many other places) for a description of the keyword.
continue is a feature of the C programming language (as well as many languages including C++, Java, etc). It is not specific to Linux.
I've often thought the name is counter-intuitive. In perl, even though much of the syntax is C-like, the keyword next is used to skip to the next loop iteration, which seems more intuitive to me.

How to handle labels in a scripting language I'm writing?

So I've been stewing over this for a long time, thinking about it. Here's a code example first, and then I'll explain it.
:main
dostuff
otherlabel
:otherlabel
dostuff
Alright so in this example, main is where the code starts, and it 'calls' the label 'otherlabel'. This is really just a shortcut for a jump command that changes execution to a different location in memory. My problem though is, how do I handle these labels so that they don't have to be declared before they are called?
At the moment, I'm doing a single step compilation reading straight from the source and outputting the bytecode. I am simply handling labels and adding them to a dictionary when I find them. And then I replace 'otherlabel' with a jump command to the correct location in code. But in this case that code wouldn't compile.
I've thought of a few ways to do this:
First is handling labels before anything else but this requires me to do everything in two steps and I have to deal with the same code twice, this slows down the process and just seems like a mess.
Second is queueing up the label calls until AFTER I've gone through the entire file and compiled everything else and then dealing with them, this seems much cleaner.
I'm writing this in C so I'd rather not implement complex data structures, I'm looking for the most straight forward way to handle this.
Use multiple passes. One pass isn't going to suffice for a scripting language, especially when you are getting to the more complex structures.
In a first pass, before compiling, construct your dictionary of labels.
In a later pass, when the compiling happens, just use that dictionary.
You could use "backpatching", although it sounds like that's what you've tried already; and it could be consstrued as a complex structure.
When you encounter a call to an undefined label, you emit the jump with a blank address field (probably into a buffer, otherwise this becomes the same as "multipass" if you have to re-read the file to patch it); and you also store a pointer to the blank field in a "patch-up" list in the dictionary. When you encounter the label definition, you fill-in all the blanks in the list, and proceed normally.

Detecting code blocks when executing a Lua script line by line

This may sound like a silly question but I could see no mention anywhere of this particular problem. Basically:
I want to execute a Lua script line by line, primarily to have the ability to pause/resume execution anytime and anywhere I want. What I do is simple: load a chunk with luaL_loadbuffer() and then issue a lua_pcall().
Thing is... How can I properly detect Lua blocks in order to execute them atomically?
For instance, suppose there's a function in the script -- by executing the file line by line with the method described above, I can't seem to have a way to properly recognize the function, and in consequence its contents are loaded and called one by one.
I can imagine that one solution would be to manually handle a stack where I push control keywords I can recognize in the script ("function", "if", "do", etc) and their corresponding "end" clause if I find nested blocks. Once I push the final "end" I call the entire block, but that sounds simply awful. Surely there must be a better way of doing this.
Hope it makes some sense, and thank you!
Please take a look at Lua coroutines to implement that functionality for scripting game entities. The idea is to yield the coroutine in the sleep() and waitforevent() routines you mentioned, and then resume later (e.g. after a timeout or event occurs).
Use lua_sethook().
Note that you probably do want to experiment with what exact hook call granularity you need. I'd recommend executing chunks of bytecode instructions instead. One really long line may contain many instructions.

Do Perl loop labels count as a GOTO?

Generally, it is good practice to avoid GOTOs. Keeping that in mind I've been having a debate with a coworker over this topic.
Consider the following code:
Line:
while( <> ) {
next Line if (insert logic);
}
Does using a loop label count as a goto?
Here is what perlsyn in perldoc has to say:
Here's how a C programmer might code up a particular algorithm in Perl:
for (my $i = 0; $i < #ary1; $i++) {
for (my $j = 0; $j < #ary2; $j++) {
if ($ary1[$i] > $ary2[$j]) {
last; # can't go to outer :-(
}
$ary1[$i] += $ary2[$j];
}
# this is where that last takes me
}
Whereas here's how a Perl programmer more comfortable with the idiom might do it:
OUTER: for my $wid (#ary1) {
INNER: for my $jet (#ary2) {
next OUTER if $wid > $jet;
$wid += $jet;
}
}
My take on this is no because you are explicitly telling a loop to short circuit and advance however my coworker disagrees, says that it is just a fancy GOTO and should be avoided. I'm looking for either a compelling argument or documentation that explains why this is or is not a GOTO. I'll also accept an explanation for why this is or is not considered good practice in perl.
Dijkstras intent was never that anything resembling goto is to be considered harmful. It was that the structure of code where gotos are used as the main construct for almost any kind of program flow change will result in what we today call spaghetti code.
You should read the original article and keep in mind that it was written in 1968 when labeled jumps was the main flow control constructs in just about all programming languages.
https://www.cs.utexas.edu/users/EWD/ewd02xx/EWD215.PDF
The danger of GOTO labels is that they create spaghetti code and make the logic unreadable. Neither of those will happen in this case. There is a lot of validity in using GOTO statements, much of the defense coming from Donald Knuth [article].
Delving into the differences between your C and Perl example... If you consider what is happening at the assembly level with your C programs, it all compiles down to GOTOs anyway. And if you've done any MIPS or other assembly programming, then you've seen that most of those languages don't have any looping constructs, only conditional and unconditional branches.
In the end it comes down to readability and understandability. Both of which are helped an enormous amount by being consistent. If your company has a style guide, follow that, otherwise following the perl style guide sounds like a good idea to me. That way when other perl developers join your team in the future, they'll be able to hit the ground running and be comfortable with your code base.
Who cares whether it counts as goto as long as it makes the code easier to understand? Using goto can often be MORE readable than having a bunch of extra tests in if() and loop conditions.
IMO, your code comparison is unfair. The goal is readable code.
To be fair, you should compare an idiomatic Perl nested loop with labels against one without them. The C style for and blocked if statement add noise that make it impossible to compare the approaches.
Labels:
OUTER: for my $wid (#ary1) {
INNER: for my $jet (#ary2) {
next OUTER if $wid > $jet;
$wid += $jet;
}
}
Without labels:
for my $wid (#ary1) {
for my $jet (#ary2) {
last if $wid > $jet;
$wid += $jet;
}
}
I prefer the labeled version because it is explicit about the effect of the condition $wid > $jet. Without labels you need to remember that last operates on the inner loop and that when the inner loop is done, we move to the next item in the outer loop. This isn't exactly rocket-science, but it is real, demonstrable, cognitive overhead. Used correctly, labels make the code more readable.
Update:
stocherilac asked what happens if you have code after the nested loop. It depends on whether you want to skip it based on the inner conditional or always execute it.
If you want to skip the code in the outer loop, the labeled code works as desired.
If you want to be sure it is executed every time, you can use a continue block.
OUTER: for my $wid (#ary1) {
INNER: for my $jet (#ary2) {
next OUTER if $wid > $jet;
$wid += $jet;
}
}
continue {
# This code will execute when next OUTER is called.
}
I think the distinction is somewhat fuzzy, but here's what the goto perldoc states about the (frowned upon) goto statement:
The goto-LABEL form finds the statement labeled with LABEL and resumes execution there.
...
The author of Perl has never felt the need to use this form of goto (in Perl, that is; C is another matter). (The difference is that C does not offer named loops combined with loop control. Perl does, and this replaces most structured uses of goto in other languages.)
The perlsyn perldoc, however, says this:
The while statement executes the block as long as the expression is true. The until statement executes the block as long as the expression is false. The LABEL is optional, and if present, consists of an identifier followed by a colon. The LABEL identifies the loop for the loop control statements next, last, and redo. If the LABEL is omitted, the loop control statement refers to the innermost enclosing loop. This may include dynamically looking back your call-stack at run time to find the LABEL. Such desperate behavior triggers a warning if you use the use warnings pragma or the -w flag.
The desperate behaviour bit doesn't look too good to me, but I may be misinterpreting its meaning.
The Learning Perl book (5th edition, page 162) has this to say:
When you need to work with a loop block that's not the innermost one, use a label.
...
Notice that the label names the entire block; it's not marking a target point in the code. [This isn't goto after all.]
Does that help clear things up? Probably not... :-)
Labeled loop jumps in Perl are GOTOs as much as C's break and continue are.
I would answer it like this, and I'm not sure if this is sufficiently different from what others have said:
Because you can only only move inside of the current scope, or to a parent scope, they're much less dangerous than what is typically implied by goto, observe:
if (1) {
goto BAR;
die 'bar'
}
BAR:
This should work obviously, but this won't (can't move in this direction).
if (0) {
BAR:
die 'bar'
}
goto BAR;
Many use cases of labels differ from goto in that they're just more explicit variants of core flow control. To make a statement that they're categorically worse would be to imply that:
LOOP: while (1) {
next LOOP if /foo;
}
is somehow worse than
while (1) {
next if /foo/;
}
which is simply illogical if you exclude style. But, speaking of style, the latter variant is much easier to read - and it does stop you from having to look up for the properly named label. The reader knows more with next (that you're restarting the loop in the current scope), and that is better.
Let's look at another example
while (1) {
while (1) {
last;
}
stuff;
}
-vs-
FOO: while (1) {
BAR: while (1) {
next FOO;
}
stuff;
}
In the latter example here next FOO, skips stuff -- you might desire this, but it is bad idea. It implies that the programmer has read a parent scope to completion which is an assumption probably better avoided. In summary, label isn't as bad as goto and sometimes they can simplify code; but, in most cases they should be avoided. I usually rewrite loops without labels when I encounter them on CPAN.
gotos are bad because they create hard to understand code--particularly, what is often called "Spaghetti Code". What's hard to understand about next Line...??
You can call it a loop "name", and it really is something to help emphasize loop boundaries. You're not jumping into an arbitrary point in relation to the loop; you're going back to the top of a loop.
Sadly enough, if it is a group or house standard, there might be nothing to convince the group that it's not a goto. I had a manager who absolutely insisted that a ternary operator made things hard to read, and preferred I use if-blocks for everything. I had a pretty good argument anything can be done in the clauses of an if-else, but that a ternary made it explicit that you were looking for a particular value. No sale.
This kind of jump is a disciplined used of a goto-like statement. So it's certainly less harmful than undisciplined use of goto. (As kasperjj wrote, "Dijkstras intent was never that anything resembling goto is to be considered harmful.")
IMO, this Perl kind of jump is even better design than C's "break" and "continue", because it makes clear what loop we break or continue, and it makes it more solid in the face of code changes. (Besides, it also allows to break or continue an outer loop.)
There are pundits who don't like break/continue and the like, but at some point there is a tradeoff to make between rules of thumb and readability, and a well-chosen break/continue or even goto may become more readable than "politically correct" code.
break/last and continue/next ARE gotos. I don't understand why anyone would go to such lengths to avoid a keyword yet use a different keyword that does the same thing...
4.4.4. Loop Control
We mentioned that you can put a LABEL on a loop to give it a name. The loop's LABEL identifies the loop for the loop-control operators next, last, and redo. The LABEL names the loop as a whole, not just the top of the loop. Hence, a loop-control operator referring to the loop doesn't actually "go to" the loop label itself. As far as the computer is concerned, the label could just as easily have been placed at the end of the loop. But people like things labeled at the top, for some reason.
Programming Perl

Resources