Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.compilers > #1142 > unrolled thread

Is multi-level function return possible?

Started bynoitalmost <noitalmost@cox.net>
First post2014-03-10 15:46 -0400
Last post2014-03-15 12:21 -0400
Articles 20 on this page of 57 — 20 participants

Back to article view | Back to comp.compilers


Contents

  Is multi-level function return possible? noitalmost <noitalmost@cox.net> - 2014-03-10 15:46 -0400
    Re: Is multi-level function return possible? Kaz Kylheku <kaz@kylheku.com> - 2014-03-11 05:20 +0000
    Re: Is multi-level function return possible? anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2014-03-11 13:04 +0000
      Re: Is multi-level function return possible? Kaz Kylheku <kaz@kylheku.com> - 2014-03-11 22:15 +0000
        Re: Is multi-level function return possible? anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2014-03-13 17:05 +0000
          Re: Is multi-level function return possible? Bill Findlay <yaldnif.w@blueyonder.co.uk> - 2014-03-14 01:28 +0000
          Re: Is multi-level function return possible? Ivan Godard <ivan@ootbcomp.com> - 2014-03-13 18:32 -0700
            Re: Is multi-level function return possible? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2014-03-14 20:27 +0000
        Re: Is multi-level function return possible? George Neuner <gneuner2@comcast.net> - 2014-03-14 02:39 -0400
          Re: Is multi-level function return possible? Kaz Kylheku <kaz@kylheku.com> - 2014-03-14 21:34 +0000
            Re: Is multi-level function return possible? Marco van de Voort <marcov@toad.stack.nl> - 2014-03-14 22:59 +0000
          Re: Is multi-level function return possible? anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2014-03-16 17:19 +0000
            Re: Is multi-level function return possible? Marco van de Voort <marcov@toad.stack.nl> - 2014-03-16 18:39 +0000
            Re: Is multi-level function return possible? Andy Walker <news@cuboid.co.uk> - 2014-03-16 19:45 +0000
              Re: Is multi-level function return possible? Bill Findlay <yaldnif.w@blueyonder.co.uk> - 2014-03-17 16:15 +0000
                Re: Is multi-level function return possible? anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2014-03-18 17:36 +0000
                  Re: Is multi-level function return possible? Andy Walker <news@cuboid.co.uk> - 2014-03-21 02:04 +0000
                    Re: Is multi-level function return possible? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2014-03-21 02:50 +0000
                      Re: design of PL/I, was Is multi-level function return possible? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2014-03-21 06:43 +0000
                      Re: design of PL/I, was Is multi-level function return possible? noitalmost <noitalmost@cox.net> - 2014-03-26 14:16 -0400
                      Re: exception catching in PL/I, was Is multi-level function return possible? "Robin Vowels" <robin51@dodo.com.au> - 2014-03-27 21:08 +1100
                    Re: Is multi-level function return possible? anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2014-03-24 17:06 +0000
                      Re: Is multi-level function return possible? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2014-03-24 20:01 +0000
                      Re: Is multi-level function return possible? George Neuner <gneuner2@comcast.net> - 2014-03-26 04:00 -0400
                        Re: Is multi-level function return possible? Hans-Peter Diettrich <DrDiettrich1@aol.com> - 2014-03-27 01:58 +0100
                          Re: Is multi-level function return possible? Stefan Monnier <monnier@iro.umontreal.ca> - 2014-04-07 14:48 -0400
                      Re: Is multi-level function return possible? Andy Walker <news@cuboid.co.uk> - 2014-03-26 12:16 +0000
                        Re: Is multi-level function return possible? Andy Walker <news@cuboid.co.uk> - 2014-03-26 17:34 +0000
                        Re: history of C, was Is multi-level function return possible? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2014-03-27 00:05 +0000
        Re: Is multi-level function return possible? Bakul Shah <usenet@bitblocks.com> - 2014-03-15 10:28 -0700
      Re: Is multi-level function return possible? George Neuner <gneuner2@comcast.net> - 2014-03-14 02:44 -0400
        Re: Is multi-level function return possible? Marco van de Voort <marcov@toad.stack.nl> - 2014-03-14 19:38 +0000
        Re: Is multi-level function return possible? Kaz Kylheku <kaz@kylheku.com> - 2014-03-14 21:36 +0000
        Re: Is multi-level function return possible? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2014-03-14 21:47 +0000
          Re: Is multi-level function return possible? Hans-Peter Diettrich <DrDiettrich1@aol.com> - 2014-03-15 13:34 +0100
        Re: Is multi-level function return possible? Ian Lance Taylor <ian@airs.com> - 2014-03-14 16:55 -0700
    Re: Is multi-level function return possible? George Neuner <gneuner2@comcast.net> - 2014-03-11 13:56 -0400
      Re: Is multi-level function return possible? federation2005@netzero.com - 2014-03-26 17:39 -0700
        Re: catch and throw, was Is multi-level function return possible? rpw3@rpw3.org (Rob Warnock) - 2014-03-27 04:23 +0000
          Re: catch and throw, was Is multi-level function return possible? Kaz Kylheku <kaz@kylheku.com> - 2014-03-27 05:44 +0000
          Re: catch and throw, was Is multi-level function return possible? Bakul Shah <usenet@bitblocks.com> - 2014-03-26 23:20 -0700
            Re: catch and throw, was Is multi-level function return possible? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2014-03-27 19:21 +0000
            Re: exception catching in PL/I "Robin Vowels" <robin51@dodo.com.au> - 2014-03-28 10:50 +1100
              Re: exception catching in PL/I Martin Ward <martin@gkc.org.uk> - 2014-04-16 14:32 +0100
            Re: catch and throw, was Is multi-level function return possible? mac <acolvin@efunct.com> - 2014-03-28 23:08 +0000
              Re: catch and throw, was Is multi-level function return possible? Ivan Godard <ivan@ootbcomp.com> - 2014-03-28 18:24 -0700
                Re: catch and throw, was Is multi-level function return possible? Kaz Kylheku <kaz@kylheku.com> - 2014-03-29 02:47 +0000
                  Re: catch and throw, was Is multi-level function return possible? Ivan Godard <ivan@ootbcomp.com> - 2014-03-28 21:32 -0700
                Re: catch and throw, was Is multi-level function return possible? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2014-03-29 03:38 +0000
                  Re: precise and imprecise, was catch and throw, was Is multi-level function return possible? Ivan Godard <ivan@ootbcomp.com> - 2014-03-28 22:12 -0700
              Re: catch and throw, was Is multi-level function return possible? Kaz Kylheku <kaz@kylheku.com> - 2014-03-29 02:07 +0000
                Re: catch and throw, was Is multi-level function return possible? Alan Bawden <alan@scooby-doo.csail.mit.edu> - 2014-03-29 02:44 -0400
              Re: PL/I exceptions, was catch and throw, was Is multi-level function return possible? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2014-03-29 02:40 +0000
                Re: PL/I exceptions "Robin Vowels" <robin51@dodo.com.au> - 2014-03-30 01:58 +1100
        Re: catch and throw, was Is multi-level function return possible? George Neuner <gneuner2@comcast.net> - 2014-03-28 03:52 -0400
    Re: Is multi-level function return possible? Louis Krupp <lkrupp@pssw.com> - 2014-03-11 15:16 -0600
    Re: Is multi-level function return possible? noitalmost <noitalmost@cox.net> - 2014-03-15 12:21 -0400

Page 2 of 3 — ← Prev page 1 [2] 3  Next page →


#1193 — Re: exception catching in PL/I, was Is multi-level function return possible?

From"Robin Vowels" <robin51@dodo.com.au>
Date2014-03-27 21:08 +1100
SubjectRe: exception catching in PL/I, was Is multi-level function return possible?
Message-ID<14-03-071@comp.compilers>
In reply to#1176
From: "glen herrmannsfeldt" <gah@ugcs.caltech.edu>
> The first language I knew with this feature is PL/I.
>
> As well as I understand it, the language was pretty well defined
> before anyone tried writing a compiler for it. They didn't ask many
> users,

The design committee organised by IBM had representatives from business, etc.

The language was to be an improved version of FORTRAN.

By the time that the PL/I language was to be designed, it was patently
evident what was wrong with existing languages.  Many years of users'
experience had already been obtained with FORTRAN, and COBOL and ALGOL
had been around nearly as long.

In the end, good features of ALGOL, FORTRAN and COBOL were merged into
the PL/I language.

> though attracting new users would have been important.  Seems
> to me they didn't ask so much what was easy to parse (among other
> features, no reserved words)

They continued the idea of FORTRAN, which did not have reserved words.
The bane of COBOL was (and still is) reserved words; ALGOL had a kind
of reserved word in the form of basic symbols, sometimes underlined,
sometimes in apostrophes, depending on the implementation; and thus
the thought that there would be no reserved words in PL/I was a very
attractive one -- and one which, in the end, proved to be the best
choice.

The basic idea of the new language was that it should be easy to use,
easy to write programs, and not to be encumbered by the numerous
exceptions that existed in FORTRAN

> and, at least the way it looks, rarely
> considered how hard it might be to generate code for, or generate
> efficient code for.
>
> Many languages were defined at the same time as the first compiler
> was written, with that compiler defining the language.

Usually there was a plan, before commencing writing, because writing a
compiler was a large task.  Undoing parts of the design and redefining
it on the fly would have been expensive in terms of man-hours.

Thus, once the PL/I language was defined, the implementing team set about
writing the compiler.

> [PL/I was, as I understand it, defined largely by glomming together
> parts of Fortran and Cobol with some bits of Algol60.  They assumed it
> would be possible to implement since all of the pieces were, although
> there turned out to be a lot of dark corners where things that seemed
> reasonable individually weren't so reasonable in combination. -John]

In the case of the FORTRAN components that were incorporated in PL/I,
most of these were considerably enhanced. The first was the
incorporation of generic built-in functions that would do away with
the need for the user having to cite by individual names functions of
different precisions (such as SIN, DSIN, etc), which would have become
unmanageable with the addition of decimal built-in functions.  The
second was a very improved FORMAT statement (or specification),
whereby repeat factors, field widths, and numbers of decimal digits,
could be specified (if required) by expressions in place of immutable
constants as was the case in FORTRAN.  The third was the
implementation of proper character handling (hands up those who recall
Hollerith constants?)

In the case of the ALGOL components incorporated into PL/I, the
obvious one was block structuring and dynamic arrays -- something that
significantly constrained users of FORTRAN.  Free form for source
statements also is an obvious steal.

Commercial facilities (particularly the data types) were modelled on those in COBOL.

Not all in PL/I was copied from other languages.

    One, I regard as one of the important innovations introduced in
PL/I was the ability to trap and handle (recover from) errors,
particularly data conversion errors, but especially subscript and
substring errors.  Many man-hours and machine hours were wasted in
trying to track down obscure errors in FORTRAN that could otherwise be
detected instantly they occurred in PL/I, and supported with
information printed out (such as values of variables; the line number
where the error occurred, and where called from).

    Other facilities included list-processing and a preprocessor.
[In that last bit I think you're confusing languages and
implementation.  WATFOR was checking for subscript and undefined data
errors on the 7040 by 1965.  Nothing new there. -John]

[toc] | [prev] | [next] | [standalone]


#1179

Fromanton@mips.complang.tuwien.ac.at (Anton Ertl)
Date2014-03-24 17:06 +0000
Message-ID<14-03-057@comp.compilers>
In reply to#1175
Andy Walker <news@cuboid.co.uk> writes:
>On 18/03/14 17:36, Anton Ertl wrote:
>> Keeping a feature may just be loyalty, but adding it back after it had
>> been removed says something about what the language designer thought
>> about the usefulness of the feature.
>
>	Well, it certainly implies that the designer [or the committee!]
>is admitting to a mistake.

In the case of the C branch of the Algol family, I very much doubt
that the designers see it that way.  B had a reduced feature set not
because the language designer did not like the features they removed,
but because B had to work on a very small machine.  They added some
features back in C, which ran on larger machines.  The designers of
C++, Java and C# are different persons than the designers of B and C,
so if they add a feature, why would they see it as "admitting to a
mistake"?

>[...]
>> "Parameters have a run-time cost": So has access to non-local
>> variables.
>
>	That depends on the machine and compiler.  The first compiler I
>used extensively [for Atlas Autocode] accessed variables at lexical
>depth N by offsetting from register N, so all variables were accessed
>at exactly the same cost.

So this compiler maintained a display in the registers.  The costs here are:

1) Accessing the variable in memory, whereas a parameter can be passed
in a register and accessed in a register.

2) Maintaining the display.  AFAIK it turned out that maintaining the
display is more costly in typical uses than the access cost it saves,
so displays fell out of favour.  This means that the run-time cost of
non-local variables is typically even more costly on this
implementation than one an implementation going using static link
chains.

- anton
--
M. Anton Ertl
anton@mips.complang.tuwien.ac.at
http://www.complang.tuwien.ac.at/anton/
[We do forget that Ritchie's C compiler ran in 12K bytes of RAM,
two passes plus assembler, and generated quite respectable code
for the PDP-11. -John]

[toc] | [prev] | [next] | [standalone]


#1180

Fromglen herrmannsfeldt <gah@ugcs.caltech.edu>
Date2014-03-24 20:01 +0000
Message-ID<14-03-058@comp.compilers>
In reply to#1179
(snip on C compilers, where our moderator wrote)

> [We do forget that Ritchie's C compiler ran in 12K bytes of RAM,
> two passes plus assembler, and generated quite respectable code
> for the PDP-11. -John]

I wonder how that compares to the PL/I (F) compiler in 44K?

Not that you would want to run it in 44K, but rumors are that it
was designed to, and will do it.

At the end of every compilation, it tells the minimum region
that will allow it to keep the symbol table in memory.

-- glen

[The F meant it was supposed to run on a 64K machine, so 44K of
available core sounds about right.  PL/I D squeezed a PL/I subset
into a 16K machine. -John]

[toc] | [prev] | [next] | [standalone]


#1182

FromGeorge Neuner <gneuner2@comcast.net>
Date2014-03-26 04:00 -0400
Message-ID<14-03-060@comp.compilers>
In reply to#1179
On Mon, 24 Mar 2014 17:06:07 GMT, anton@mips.complang.tuwien.ac.at
(Anton Ertl) wrote:

>So this [Atlas] compiler maintained a display in the registers.
>The costs here are:
>
>   :
>
>2) Maintaining the display.  AFAIK it turned out that maintaining the
>display is more costly in typical uses than the access cost it saves,
>so displays fell out of favour. This means that the run-time cost of
>non-local variables is typically even more costly on this implementation
>than one an implementation using static link chains.

I think it was more the expanded use of techniques like closure
conversion and lambda lifting that allowed rewriting nested code so as
to eliminate non-local accesses or to make them, at most, single
indirections through local pointers.

In any event, static links are more performant only when there is
relatively little use of deep non-locals - if you are often chasing
more than 2 links, you're better off using a display.  Unfortunately,
although a compiler can determine the number of non-locals and the
number of lexical levels involved, it can't determine frequencies of
access so as to make an intelligent decision regarding implementation.

The instruction cost is slightly greater to maintain a display than to
maintain a static chain, but if the display is in suitably fast memory
- in registers or locked into cache - the actual difference in *time*
spent on maintenance may be insignificant.

Moreover, the maximum depth of display for any call chain can be
statically determined and a display does not have to be large to be
very effective: I recall usage studies of non-locals in programs
written in various languages - Algol, Pascal, Lisp, etc. - showing
that 4 levels was sufficient for ~80% of the code and 8 levels was
sufficient to handle very nearly all of it.  IIRC, less than 0.1% of
all the code studied needed 16 or more levels.

I suspect that if similar studies were done today using modern nested
languages they would find very little difference: most programmers
just don't write very deeply *scoped* nested code - they tend to
create relatively shallow closures instead.  And then the compiler
flattens the closures so all the variables within are a single
indirection regardless of lexical level.  I.e. no more need for any
non-local mechanism.

You can (maybe) argue that a display in registers is wasteful and that
the registers could be put to better use.  OTOH, the machine in
question may have had memory mapped pseudo-registers or a similar fast
RAM area for holding frequently used variables.  Even if the registers
were real, they may have been dedicated to addressing/indexing anyway.

YMMV,
George

[toc] | [prev] | [next] | [standalone]


#1189

FromHans-Peter Diettrich <DrDiettrich1@aol.com>
Date2014-03-27 01:58 +0100
Message-ID<14-03-067@comp.compilers>
In reply to#1182
George Neuner schrieb:

> The instruction cost is slightly greater to maintain a display than to
> maintain a static chain, but if the display is in suitably fast memory
> - in registers or locked into cache - the actual difference in *time*
> spent on maintenance may be insignificant.

Many years ago I found a funny implementation of local variables in
GfA-Basic. As opposed to most (all?) other compilers, on entry of a
subroutine the *global* variables; matching the name of a local
variable or parameter; were pushed onto the stack and re-initialized
for use inside the subroutine, and restored on exit. This allows to
access all currently living variables from everywhere in the code. It
also allows for by-name references when the table of variables is
prepared accordingly, as was the case in traditional Basic. Dunno how
Algol implemented this and its many other exotic parameter passing
conventions.

I found that implementation so exciting, that I think it's worth to be
mentioned here.

DoDi
[That's approximately what Lisp calls shallow binding.  For Algol60
call by name, which was a mistake, it needed the Pascal display or the
equivalent, and arguments had to be callback routines (thunks) to
allow them to recompute the expression values. -John]

[toc] | [prev] | [next] | [standalone]


#1210

FromStefan Monnier <monnier@iro.umontreal.ca>
Date2014-04-07 14:48 -0400
Message-ID<14-04-003@comp.compilers>
In reply to#1189
> Many years ago I found a funny implementation of local variables in
> GfA-Basic.
[ Describes the mechanism used, e.g. in Emacs.  ]

This gives you dynamic scoping: no closures.


        Stefan

[toc] | [prev] | [next] | [standalone]


#1183

FromAndy Walker <news@cuboid.co.uk>
Date2014-03-26 12:16 +0000
Message-ID<14-03-061@comp.compilers>
In reply to#1179
On 24/03/14 17:06, Anton Ertl wrote:
>>> Keeping a feature may just be loyalty, but adding it back after it had
>>> been removed says something about what the language designer thought
>>> about the usefulness of the feature.
>> 	Well, it certainly implies that the designer [or the committee!]
>> is admitting to a mistake.
> In the case of the C branch of the Algol family, I very much doubt
> that the designers see it that way.  B had a reduced feature set not
> because the language designer did not like the features they removed,
> but because B had to work on a very small machine.  They added some
> features back in C, which ran on larger machines.

	But B and C are different languages, with differing design aims
and criteria.  Having a feature in C that was absent from B is not the
same as adding to C a feature that had previously been removed.  K&R C
was not B Mk 2, but a new language with inputs [conscious or unconscious]
from many languages, including (B)(CPL) and Algol 68.

	OTOH, modern versions of C have several features missing from
K&R C but present in [eg] Algol.  Presumably the committee at least
feels that their omission had been a mistake;  I don't know whether K&R
felt the same way.

>						   The designers of
> C++, Java and C# are different persons than the designers of B and C,
> so if they add a feature, why would they see it as "admitting to a
> mistake"?

	Again, these are different languages and it's one thing to design
a new language with new aims [which may include being leaner and meaner
than earlier languages], and quite another to revise a language to include
features previously dropped.

>> [...]
>>> "Parameters have a run-time cost": So has access to non-local
>>> variables.
>> 	That depends on the machine and compiler.  The first compiler I
>> used extensively [for Atlas Autocode] accessed variables at lexical
>> depth N by offsetting from register N, so all variables were accessed
>> at exactly the same cost.
> So this compiler maintained a display in the registers.  The costs here are:
> 1) Accessing the variable in memory, whereas a parameter can be passed
> in a register and accessed in a register.

	As above, it depends on the machine and compiler.  On Atlas, the
registers were 24 bits whereas most parameters were 48 bits.  Integers
were usually stored as denormalised reals [ie, also 48 bits] because
multiplications and divisions had to be done in the accumulator anyway
[and there were only very limited shift instructions].

> 2) Maintaining the display.  AFAIK it turned out that maintaining the
> display is more costly in typical uses than the access cost it saves,
> so displays fell out of favour.

	Well, it's one instruction on entry to a procedure and one on
exit, so it's not exactly expensive.  It's certainly cheaper than passing
several parameters around all the time, so the overall balance depends on
how many and how often intermediate variables are used.  I thought that
displays fell out of favour more because of a paucity of registers?  Not
many minis and micros had the 100+ available to the general user on Atlas.

	But in any case, you are again looking only at the cost in terms
of computing resources, and not at the programmer's view.  The notions of
"literate" or "top-down" programming may have fallen out of favour, but
in the pre-Unix era [after which the emphasis switched to tools and to
libraries] it was natural to write programs in the form of nested
procedures, each of which was expanded in turn as the program developed.
Functions also were naturally written within the procedures where they
were used, and variables were declared at the most natural level for
their life-times.  It's not impossible to write C programs that way, but
it's much harder than the equivalent [eg] Pascal.

> [We do forget that Ritchie's C compiler ran in 12K bytes of RAM,
> two passes plus assembler, and generated quite respectable code
> for the PDP-11. -John]

	12K?  Luxury.  Why, in my day, ....  But some early compilers ran
in ridiculously small computers by modern standards.

--
Andy Walker,
Nottingham.
[C was influenced by PL/I.  C++ is where the Algol68 got mixed in, and some
of the C++ stuff was backported into C. -John]

[toc] | [prev] | [next] | [standalone]


#1184

FromAndy Walker <news@cuboid.co.uk>
Date2014-03-26 17:34 +0000
Message-ID<14-03-062@comp.compilers>
In reply to#1183
On 26/03/14 12:16, the Moderator wrote:
> [C was influenced by PL/I.  C++ is where the Algol68 got mixed in, and some
> of the C++ stuff was backported into C. -John]

	Dennis Ritchie, in "The Development of the C Language" [online at
"http://cm.bell-labs.com/cm/cs/who/dmr/chist.pdf"] quotes three influences
of PL/I: comments, file inclusion and the use of "pointer->member" even when
"pointer" has the wrong type.  OTOH, he quotes four influences of Algol 68:
the notation for assignment operators, the scheme of type composition, unions
and casts.  Wiki also quotes him as saying "And yes, of course, "long".".
Make of that what you will, but it all pre-dates C++.  It is also getting
away from debate about compilers ....

--
Andy Walker,
Nottingham.
[I went back and reread the paper. You're right. -John]

[toc] | [prev] | [next] | [standalone]


#1186 — Re: history of C, was Is multi-level function return possible?

Fromglen herrmannsfeldt <gah@ugcs.caltech.edu>
Date2014-03-27 00:05 +0000
SubjectRe: history of C, was Is multi-level function return possible?
Message-ID<14-03-064@comp.compilers>
In reply to#1183
Andy Walker <news@cuboid.co.uk> wrote:

(snip)

>        But B and C are different languages, with differing design aims
> and criteria.  Having a feature in C that was absent from B is not the
> same as adding to C a feature that had previously been removed.  K&R C
> was not B Mk 2, but a new language with inputs [conscious or unconscious]
> from many languages, including (B)(CPL) and Algol 68.

(snip)

> [C was influenced by PL/I.  C++ is where the Algol68 got mixed
> in, and some of the C++ stuff was backported into C. -John]

I always believe that until a recent comp.lang.c discussion convinced
me otherwise.

The question related to the C conditional operator, which I remembered
in a different form from ALGOL-10 (on TOPS-10) some years ago.

I then looked up in ALGOL-60 and ALGOL-68 manuals to find out how it
changed. Seems that ALGOL-68 also has the assign/arithmetic operators,
such as +:=, -:=, x:- (where that should be a multiply sign, not an
x or *), and some more that I also don't have on the keyboard.

PL/I doesn't (or at least didn't, could have changed by now) have the
conditional operator or the assign/arithmetic operators. Both of
those, at least, go back to K&R C, and before C++.

PL/I is from around 1964 or so, but I don't know the timing
(what happened when) for ALGOL-68 at all.

The two differences I always remember between K&R C and ANSI C are
struct as argument (instead of struct pointer) and initialized auto
arrays.

-- glen

[toc] | [prev] | [next] | [standalone]


#1164

FromBakul Shah <usenet@bitblocks.com>
Date2014-03-15 10:28 -0700
Message-ID<14-03-042@comp.compilers>
In reply to#1147
On 3/11/14, 3:15 PM, Kaz Kylheku wrote:
 >
 > Recursion means there is possibly more than one activation of the environment
 > which contains the target label of the goto. Which activation is chosen as the
 > jump target? Does the goto return to the same recursion level in which
 > the closure was created or does it just find the innermost activation of
 > that label?
 >
 > If the closure jsut goes to the innermost block which has the label,
 > then the target resolution is in fact dynamically scoped, even though
 > the label is lexical. (Because the target block is not lexically captured
 > along with the closure, but chosen just from whatever is visible at the
 > time the goto takes place.)

No, the label/goto scoping is strictly lexical. What happens is you
pop all the frames until you reach the frame of the correct lexically
enclosing routine with the defined label and then set PC to the
address of the instruction the label points to.

Here's a convoluted example using C syntax (but Pascal's goto and
nested function semantics):

typedef int(*int_f)(int);

int fun(int_f g) {
          return g(1) + g(0);
}

int top(int v, int_f f) {
          int sub(int x) {
                  if (x == 0)
                          goto lab1;
                  return x+1;
          }
          int HOfun(int_f argfun1) {
                  top(v-1, argfun1);
          }
          if (v > 1)
                  return HOfun(sub);
          return fun(f);
lab1:
          return -1;
}

When top is called with v=2 and f=some random function, it
will call HOfun with argfun1=sub.  HOfun calls top again and
passing its argfun1.  Now top calls fun with the passed in
function, which sub (but from the previous call to top).  When
fun calls g (which is really sub) with x=0, the stack has
these activation frames:

top // original call
HOfun
top  // call from HOfun
fun
sub

Since sub's static link points to the frame of the original call to
top, four frames will be popped & PC set to the instruction named by
lab1. BTW, label declarations have to precede function/procedure
declarations so that a one pass compiler can identify the correct
enclosing scope!

[toc] | [prev] | [next] | [standalone]


#1153

FromGeorge Neuner <gneuner2@comcast.net>
Date2014-03-14 02:44 -0400
Message-ID<14-03-031@comp.compilers>
In reply to#1144
On Tue, 11 Mar 2014 13:04:57 GMT, anton@mips.complang.tuwien.ac.at
(Anton Ertl) wrote:

>... in Pascal you can goto a label that is in a containing procedure
>or function, even across several levels.  That is a very rarely used
>feature of the language, and Wirth removed it (along with goto) from
>his later languages.

Interesting.  I was not aware of this, and it is not mentioned in any
of several Pascal books I have from the early 80's.  Other than
Wirth's own, I wonder how many implementations actually allowed it?

George

[toc] | [prev] | [next] | [standalone]


#1155

FromMarco van de Voort <marcov@toad.stack.nl>
Date2014-03-14 19:38 +0000
Message-ID<14-03-033@comp.compilers>
In reply to#1153
On 2014-03-14, George Neuner <gneuner2@comcast.net> wrote:
>>... in Pascal you can goto a label that is in a containing procedure
>>or function, even across several levels.  That is a very rarely used
>>feature of the language, and Wirth removed it (along with goto) from
>>his later languages.
>
> Interesting.  I was not aware of this, and it is not mentioned in any
> of several Pascal books I have from the early 80's.  Other than
> Wirth's own, I wonder how many implementations actually allowed it?

GPC and several of the other ISO aspirants I assume. Free Pacal added it in
its ISO mode too, though much more recently (afaik the current production
2.6.x series).

Some examples are in the testsuite here:
http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/tests/test/

tisogoto* are the interprocedural goto tests, specially
http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/tests/test/tisogoto1.pp?revision=15710&view=markup

tmaclocalprocparam* are the closurelike functionality

P.s. Delphi 2009 has a closure like feature too, called "anonymous methods".

[toc] | [prev] | [next] | [standalone]


#1158

FromKaz Kylheku <kaz@kylheku.com>
Date2014-03-14 21:36 +0000
Message-ID<14-03-036@comp.compilers>
In reply to#1153
On 2014-03-14, George Neuner <gneuner2@comcast.net> wrote:
> On Tue, 11 Mar 2014 13:04:57 GMT, anton@mips.complang.tuwien.ac.at (Anton Ertl) wrote:
>
>>... in Pascal you can goto a label that is in a containing procedure
>>or function, even across several levels.  That is a very rarely used
>>feature of the language, and Wirth removed it (along with goto) from
>>his later languages.
>
> Interesting.  I was not aware of this, and it is not mentioned in any
> of several Pascal books I have from the early 80's.

Maybe it was considered the "underwear" of the implementations,
hence one of the "unmentionables".

[toc] | [prev] | [next] | [standalone]


#1159

Fromglen herrmannsfeldt <gah@ugcs.caltech.edu>
Date2014-03-14 21:47 +0000
Message-ID<14-03-037@comp.compilers>
In reply to#1153
George Neuner <gneuner2@comcast.net> wrote:
> On Tue, 11 Mar 2014 13:04:57 GMT, anton@mips.complang.tuwien.ac.at
> (Anton Ertl) wrote:

>>... in Pascal you can goto a label that is in a containing procedure
>>or function, even across several levels.  That is a very rarely used
>>feature of the language, and Wirth removed it (along with goto) from
>>his later languages.

> Interesting.  I was not aware of this, and it is not mentioned in any
> of several Pascal books I have from the early 80's.  Other than
> Wirth's own, I wonder how many implementations actually allowed it?

As I remember it, Pascal allows GOTO out of an internal procedure.
That might not look so significant in the book, but, especially in
the case of recursion, it gets interesting when you have to implement
it.

Some of the programs that go along with TeX use it, I believe DVItype
being one. Some years ago, I translated one to C, and so used
longjmp() for the first, and probably last, time. (That was not so
long after I started working with C.)

TeX and associated programs were originally all in Pascal, but using
Knuth's preprocessor to make them more readable, what he calls
Literate Programming. Among other features that he discusses, is that
Pascal GOTO uses numeric labels, apparently to discourage their use.
Part of Literate Programming is to use alphanumeric, more descriptive
labels. But as with many GOTO statements, the usual use is getting out
in the case of a fatal error, even from nested procedure calls.

In addition to what Pascal allows, C's longjmp() and PL/I with LABEL
variables, allow run-time selection of targets.  That is, with a
variable instead of a compile-time constant label.

-- glen
[I thought the numeric labels were to look like Fortran. -John]

[toc] | [prev] | [next] | [standalone]


#1162

FromHans-Peter Diettrich <DrDiettrich1@aol.com>
Date2014-03-15 13:34 +0100
Message-ID<14-03-040@comp.compilers>
In reply to#1159
> [I thought the numeric labels were to look like Fortran. -John]

IMO it's a LL(1) thing. Statements cannot start with a number, so it
must be a label.

DoDi
[It's as good (or bad) a reason as any. -John]

[toc] | [prev] | [next] | [standalone]


#1161

FromIan Lance Taylor <ian@airs.com>
Date2014-03-14 16:55 -0700
Message-ID<14-03-039@comp.compilers>
In reply to#1153
George Neuner <gneuner2@comcast.net> writes:

> On Tue, 11 Mar 2014 13:04:57 GMT, anton@mips.complang.tuwien.ac.at
> (Anton Ertl) wrote:
>
>>... in Pascal you can goto a label that is in a containing procedure
>>or function, even across several levels.  That is a very rarely used
>>feature of the language, and Wirth removed it (along with goto) from
>>his later languages.
>
> Interesting.  I was not aware of this, and it is not mentioned in any
> of several Pascal books I have from the early 80's.  Other than
> Wirth's own, I wonder how many implementations actually allowed it?

I don't know about Pascal implementations, but GCC supports nested
functions as an extension to C, and supports doing a goto to a label
defined in an enclosing function.

There is an example in the docs at
http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/Nested-Functions.html .

Ian

[toc] | [prev] | [next] | [standalone]


#1145

FromGeorge Neuner <gneuner2@comcast.net>
Date2014-03-11 13:56 -0400
Message-ID<14-03-023@comp.compilers>
In reply to#1142
On Mon, 10 Mar 2014 15:46:31 -0400, noitalmost <noitalmost@cox.net>
wrote:

>Is [multi-level return] a doable thing for a Pascal-like language that is
>meant to be compiled? I have a multi-level break which works within a
>procedure, but the return across procedure boundaries seems to add a lot
>of complications.
>
>I don't recall this being discussed in the dragon book, perhaps because it's
>just a silly idea. But implementing the multi-level break got me curious
>whether it's possible.

The modern term is "exception".  See also "non-local" control
transfer, exit and/or return, and "escape" or "backtracking"
continuation.

I don't have my book handy to check but I *think* the purple dragon
has a discussion of exceptions.  I'm pretty sure the older books don't
explicitly cover non-local control transfer, but careful reading of
the sections on control flow should allow inferring an implementation.


>[Sure, you can do it.  PL/I let you jump out of a routine and I think Algol60
>may have, too.  You just need to keep your stack frames sufficiently linked
>so that you can find the one you want and unwind everything below it.  Look
>at the way Algol and Pascal reference variables in blocks outside the current
>routine and you'll get most of what you need. -John]

The real issue is whether you simply need to abort the computation
(perhaps with a return value) or whether you need to clean up side
effects: e.g., free heap allocations, restore variable values, etc.
The OP describes the language as "Pascal-like", but that doesn't
necessarily mean "simple" ... there certainly are modern OO and GC'd
Pascal derivatives for which the notion of "cleaning up" after an
exception can be quite involved.

The most primitive mechanism - performing only control transfer - is
something like C's setjmp/longjmp: you save the return point register
state (as if you are calling a function [even if you aren't]) and you
arrange that the state is [at least name] visible to the lower level
functions.  In a Pascal-like language the simplest thing is just to
keep the saved state on the stack as a local variable of the
upper-most function and let lower functions refer to it as a non-local
variable.

George

[toc] | [prev] | [next] | [standalone]


#1187

Fromfederation2005@netzero.com
Date2014-03-26 17:39 -0700
Message-ID<14-03-065@comp.compilers>
In reply to#1145
On Tuesday, March 11, 2014 12:56:01 PM UTC-5, George Neuner wrote:
> The modern term is "exception".  See also "non-local" control
> transfer, exit and/or return, and "escape" or "backtracking"
> continuation.

Right, the contemporary (not "modern") [Note 1] notion is the
catch-throw paradigm. I like to think of it as the "cap and trap"
mechanism.

I believe it originates with Prolog in the 1970's, since (a) catch and
throw are part of Prolog's library of built-in functions, and (b) the
multi-level breakout has always been an integral part of its run-time
system.

Some C compilers implement it as well, not just C++. And in more
recent times (i.e. since the late 20th century) it's found its way
directly in the CPUs' architectures as a kind of alternative to the
"interrupt".

The idea may also be motivated, in part, by the Curry-Howard
isomorphism, which relates the "AND", "OR" and "IF-THEN" connectives
of Intuitionist logic respectively to the product, union and function
types. When the scope of the correspondence is extended to classical
logic, it connects Pierce's Rule to the catch-throw mechanism. Look
under the Wikipedia entry, for instance, which also points to the
call/cc mechanism of Scheme and to the related notion of continuation
passing.

Note 1:
USENET articles are read as much as 33 years after they're written (so far),
by an audience who will see "modern" as parochially "presentist", i.e. 33
years dated. Google's people have been guilty of this too, lately.

[toc] | [prev] | [next] | [standalone]


#1190 — Re: catch and throw, was Is multi-level function return possible?

Fromrpw3@rpw3.org (Rob Warnock)
Date2014-03-27 04:23 +0000
SubjectRe: catch and throw, was Is multi-level function return possible?
Message-ID<14-03-068@comp.compilers>
In reply to#1187
<federation2005@netzero.com> wrote:
+---------------
| George Neuner wrote:
| > The modern term is "exception".  See also "non-local" control
| > transfer, exit and/or return, and "escape" or "backtracking"
| > continuation.
|
| Right, the contemporary (not "modern") notion is the catch-throw
| paradigm. I like to think of it as the "cap and trap" mechanism.
|
| I believe it originates with Prolog in the 1970's, since (a) catch
| and throw are part of Prolog's library of built-in functions, and
| (b) the multi-level breakout has always been an integral part of
| its run-time system.
+---------------

According to Gabriel and Steele in "The Evolution of Lisp"[1],
Lisp 1.5 [early 1960s] had (ERRSET form), which:

    ...evaluates *form* in a context in which errors do not terminate
    the program or enter the debugger. If *form* does not cause an
    error, ERRSET returns a singleton list of the value. If execution
    of *form* does cause an error, the ERRSET form quietly returns NIL.

    MacLisp [late 1960s] added the function ERR, which signals an error.
    If ERR is invoked within the dynamic context of an ERRSET form, then
    the argument to ERR is returned as the value of the ERRSET form.
    Programmers soon began to use ERRSET and ERR not to trap and signal
    errors but for more general control purposes (dynamic non-local exits).
    Unfortunately, this use of ERRSET also quietly trapped unexpected
    errors, making programs harder to debug. A new pair of primitives,
    CATCH and THROW, was introduced into MacLisp in June 1972 so that
    ERRSET could be reserved for its intended use of error trapping

So unless Prolog's implementation predates June 1972, I would suggest
that Lisp has priority on CATCH/THROW.


-Rob

[1] http://www.dreamsongs.com/Files/Hopl2.pdf
    The Evolution of Lisp
    Guy L. Steele Jr. & Richard P. Gabriel
    [Presented at the ACM/SIGPLAN Second History of
    Programming Languages Conference, April 1993]

[2] http://www.dreamsongs.com/Files/HOPL2-Uncut.pdf
    [Uncut version, contains ~32 pages of material
    trimmed from conference version.]

-----
Rob Warnock		<rpw3@rpw3.org>
627 26th Avenue		<http://rpw3.org/>
San Mateo, CA 94403
[I happen to have a copy of the LISP 1.5 Programmer's Manual, second
edition, in my hand, and while it says nothing about ERRSET, on page
35 it does describe a form called errorset[] that evaluates an
expression and returns a list of the expression's value if it worked,
or nil if there was an error.  Page 32 alludes to an error[] form that
causes an error.  Sure sounds like catch and throw to me, give or take
the problem that it also catches and ignores real errors.  The book
was published in 1965. -John]

[toc] | [prev] | [next] | [standalone]


#1191 — Re: catch and throw, was Is multi-level function return possible?

FromKaz Kylheku <kaz@kylheku.com>
Date2014-03-27 05:44 +0000
SubjectRe: catch and throw, was Is multi-level function return possible?
Message-ID<14-03-069@comp.compilers>
In reply to#1190
On 2014-03-27, Rob Warnock <rpw3@rpw3.org> wrote:
> According to Gabriel and Steele in "The Evolution of Lisp"[1],
> Lisp 1.5 [early 1960s] had (ERRSET form), which:
>
>     ...evaluates *form* in a context in which errors do not terminate
>     the program or enter the debugger. If *form* does not cause an
>     error, ERRSET returns a singleton list of the value. If execution
>     of *form* does cause an error, the ERRSET form quietly returns NIL.
> ...

Before this, Lisp-2, around 1965 or 1966, already had TRY and EXIT,
which looked like a predecessor to catch, and a close relative of this
ERRSET, while also hinting at unwind-protect also (although, in
contrast, unwind-protect doesn't serve as the ultimate termination
point of a control transfer, but only a "pit stop").

TRY went something like this:

  (TRY <var> <protected-statemenet> <cleanup-statement>)

TRY evaluates <protected-statement>. If an (EXIT <val>) does not occur
in that evaluation, then when <protected-statement> terminates, the
TRY terminates and control passes to whatever form is next.

If an (EXIT <val>) operation occurs in <protected-statement>, then
variable <var> is bound to the value <val>, and <cleanup-statement> is
executed in scope of that variable. The exit is thereby intercepted,
and control continues with whatever is next after the TRY.

[toc] | [prev] | [next] | [standalone]


Page 2 of 3 — ← Prev page 1 [2] 3  Next page →

Back to top | Article view | comp.compilers


csiph-web