From: lasner@watsun.cc.columbia.edu (Charles Lasner)
Newsgroups: alt.folklore.computers
Subject: Re: The need for an assembler (was: Favorite CPU)
Date: 29 Aug 92 21:56:59 GMT
Reply-To: lasner@watsun.cc.columbia.edu (Charles Lasner)
Organization: Columbia University

In article <NEERI.92Aug27180026@iis.ethz.ch> neeri@iis.ethz.ch (Matthias Neeracher) writes:
>In article <1992Aug27.075325.16635@news.columbia.edu> lasner@watsun.cc.columbia.edu (Charles Lasner) writes:
>>In article <NEERI.92Aug26154345@iis.ethz.ch> neeri@iis.ethz.ch (Matthias Neeracher) writes:
>>>
>>>>The test for the condition is 
>>>>whether it's possible to transfer out of a loop, and then go back in with
>>>>out losing any context,
>>>
>>>This is clearly illegal in Pascal.
>>
>>You left out the other half of the test, which was to stay within a larger
>>loop structure surrounding the exited loop without loss.
>
>And this is clearly *legal*.

Yes, but no.  You can't rejoin where you were by jumping back to the same
level of the loop you formerly were in.  Also, I guess you don't realize that
when you do this form of "panic" exit, the language spec is sloppy enough
that the stack can "grow" because of junk left behind.  There are some
implementations that do this.

In any case, this is an arbitrary lame restriction of the language.  PL/I
came first; it and Fortran allow unchanged loop re-entry.  It is too much of
a cheap compiler solution to disallow this form than any other design reason
to disallow it.  A "smarter" compiler knows how to make this usage innocuous.
Since PASCAL arised out of a half-baked academic project, it's no surprise
that it has expedient restrictions.

>
>>The point of the matter is that by making it illegal, you limit the ability to
>>create straight-forward structures without resorting to "equivalent" forms
>>that sometimes aren't so equivalent.
>
>Jumping out of a loop and back in again is straight-forward ? Show me an
>algorithm where the straight-forward solution consists of jumping out and into
>a loop.

Very simple, to conditionally call some code that isn't really a subroutine,
but can exist outside of the loop.  Subroutine calls in many languages are
often an "expensive" overhead in the running program.  Ask some of the people
who have posted here who run "real* applications (crunch-wise).  Some people
nitpick about "peep-hole" techniques, etc., when this could be a glaring 
fault.  Abiding by this restriction begs the larger category of having to
not call subroutines but instead (macro-style) regenerate the code multiple
times in-line.  In some programs as posters explained, this is unacceptable
due to the unwieldiness of the overall program, etc.

This is a quite old technique, and can be applied rather elegantly.  Designing
a language to cramp legitimate style is not my idea of a good language design.
You can never have too many ways to express a problem solution.  I suggest that
Pascal has a "skew" in it to serve the interests of groups that would 
essentially limit "programming freedom" to their "brand" of programming methods
and techniques *only*.  This is one of the arguments on why to program in
assembler: you make up your own rules to fit your own skills, preferences, 
and the parameters of the problem.  PASCAL "mentality" is the square peg in
the round hole variety.

>
>>By declaring it illegal, you allow the
>>compiler to "cop out" regarding stack marking, etc., so a sloppier code
>>generation is acceptable.
>
>Making the compiler's job easier is only part of the reason (do I understand
>you correctly that you resent this restriction *because* it allows the compiler
>to generate efficient code ?). Another important reason is predictability. The
>only HLLs I know that allow jumping back into loops are Fortran and some BASIC
>dialects (I don't know PL/I, nor do I have a real desire to know). The BASIC
>solution leaves the stack in a mess, while Fortran merely leaves the
>Programmer's mind in a mess. In neither language have I seen a convincing
>reason to allow jumping into loops. 

Efficiency of running code isn't a factor here either way, as it is possible
to do a good/bad job in either scenario of a language with/without the
relevant features.  Clearly, one branch or jump or skip instruction is the
only possible "overhead" either way in the running code assuming all else was
laid out suitably.

I strongly suggest you look at PL/I rather closely.  Various "scientific"
subsets have been written over the years to avoid all of the IBM "overhead"
of decimal arithmetic and other "extraneous" data types retaining otherwise
total feature compatibility, etc.

BTW, I never said jumping *into* loops, I said rejoining them.

>>[...] I prefer to take this argument to be PASCAL versus PL/I.  In PL/I
>>the functions are recursive or not as I choose,
>
>Why should a programmer have to specify that a function is recursive? That's
>what compilers are for.

Wrong, cheap compilers and simplified language specs are for allowing the
compiler to be a shoddy implentation of a shoody language.  The compiler
can't possibly know what you have in mind, so you have to tell it what you
intend.  Clearly, most reasonable architectures have subroutine call methods
that can take advantage of non-stack less-cycle methods.  In the process,
the subroutine call is not recursive, since nothing gets saved on a stack.
For an entire class of problems, this is quite acceptable, although clearly
not for everything.  PASCAL for example totally cops out on this point, and
doesn't have syntax to instruct the compiler as to your intention, thus all
calls are the high-overhead kind; there's just no way to specify the more
efficient alternatives.  (If you are only familiar with machine architectures
where the subroutine call mechanism is *only* via stack then you are totally
missing this point.  Such machines are inherently inferior on this aspect of
their design compared to otherwise better machines with a choice.  The PDP-10
architecture is a good example of a machine with more than 2 methods of
routine call so recursion is possible, but not thrust upon you where it would
only accomplish inefficiency.

In any case, PL/I is a language where you can inform the compiler that the
subroutine is intended for either recursive (stack-save) or non-recursive
(no stack-save) calling convention, and reap the benefits.  You regain total
control over your architecture on this point while PASCAL ignores this issue
totally.

>
>>Globality of variables is
>>determined by my usage, not by arbitrary wimpy restrictions of the compiler,
>
>*Shudder*. How exactly does this work ?

Very simple:

I can use true top-down order, or PASCAL-like order, or anything else I
choose.  The scope of variables is determined by my placement of their
declarations.  Since internal procedures can be defined within internal
procedures if need be, the relative globality is a vast superset of what
PASCAL allows, and with total freedom of statement order to suit what I choose,
not what a cheap compiler forces me into for the sake of ease of the design
and implementation of the compiler itself.  There's a fundamental conceptual
problem here: is the compiler written to suit the programmer, or is the
programmer here to suit the compiler?

Notice that data types can be as rigorous as I want, although Fortran-style
defaults (I-N rule) apply (and can be defeated if you insist as an 
implementation option or compiler switch).

>
>>and all labels are equally symbolic.
>
>I can have symbolic labels in C, too.

Good point, but not in PASCAL unless you want to be non-standard, and then
not necessarily.

>
>>>>Why would I want to use a language where you need
>>>>FORWARD statements because it doesn't do enough passes to do it without me?
>>>
>>>Why slow the compiler down for programmers who wouldn't use the language
>>>anyway :-)
>>
>>A silly remark that doesn't answer the question.
>>This is a major ugly
>>feature of the language: all internal procedures have to come first, and
>>when they reference each other, a kludge is needed to pull it off.
>
>One reason for this is that if the rest of the language can be compiled in a
>single pass, the incentive to add a whole compiler pass for this minor problem
>is not that great (Interestingly, the original compiler for Modula-2 was a
>4 or 5 pass compiler, and Modula-2 didn't have forward declarations. When the
>compiler was rewritten as a one pass compiler, forward declarations returned).

Why should I care about how many passes a compiler makes over my code?  This
is a ludicrous issue, since a compiler can tokenize my input down to a
much smaller size and then make fast passes over that in short order.  Also,
with larger and larger machines these days, who cares how much memory it 
takes to compile in?  Passes can mostly be ignored if a memory-resident copy
of the tokenized form is what's being multiply passed over!  Perhaps this is
a down side of the coin about "modern" compilers: they are cheap 
implementations that take shortcuts as compared to "older" compilers.

>
>Another resaon for forward declarations is that it faciliates a sequential
>reading of the code.

I never said to remove the feature, just to not require it as a kludge to
solve the chicken-egg problems of PASCAL.  As I pointed out earlier, in PL/I
I can order it any way I want, including precisely as in PASCAL.

>
>>An
>>additional minor peeve: when the arg list for the function that was
>>forwarded is now known, why must it be left out of the definition.  I
>>have seen comments that attempt to fantasize about the repetition of the
>>arg list, but why do you have to leave it out?
>
>The reason is probably simple and ugly: Because it would cost time for the
>compiler to check the arguments and it would be dangerous for maintenance to
>leave them unchecked.

[Modula-2 stuff deleted]

I would think that it's dangerous for maintenance that people are in fact
creating fantasy lists of args passed in the *comment* after the stubbed
header.  Again, why should I care about an insignificent amount of scan
time of a compiler?  This isn't a pass we're discussing, since the
comment has to be parsed anyway, rather just the appropriate lookups for
the items in question already present from the FORWARD statement.

>>>>poorly-formed GOTOs could be harmful.)
>>>
>>>And lots of well formed GOTOs unnecessary in modern languages.

Unnecessary is again an opinion, I prefer "can be worked around for the
lack thereof sometimes with the consequences of implementing more inefficient
structures in the process".

>>
>>[...]  And unnecessary isn't a
>>replacement for undesirable.  Why have a language that limits my ability
>>to express ideas in alternate ways?
>
>A programming language that allows too many ways to express the same idea is
>likely to produce "sublanguages", i.e., Programmers use exclusively a subset of
>the language and different programmers use different subsets.

I would *hope* that this would occur.  It helps point out where language
elements are excess baggage.  I doubt if anything is gained by removing
freedom of choice of a method.  This is starting to sound like "Big Brother
programming".

>
>>BTW, if HLL theory is that it abstracts what computers actually do,
>>then why the deficiency in so many languages regarding goto?  Do people
>>believe that computers lack program control branch instructions?
>
>No, but they believe that it's useful to abstract from them. A majority of
>computers today seem to also have a condition code, but that doesn't
>necessarily mean that its a good idea to create a programming language that
>allows the following:
>
>begin
>   compare b to c;
>   BMI negative;
>
>   d := 2;
>
>negative:
>end;

No one is suggesting that.  Merely the use of an unrestricted goto as an
element to possibly be combined.  If-then-goto as a primary example, but
not just that.

Admit it: there seems to be a "political" undertone to the implications of
this discussion.  I am for more, not less, programming freedom.

cjl
Newsgroups: alt.folklore.computers