From: | Paul Robinson <postmaster@paul.washington.dc.us> |
Newsgroups: | comp.compilers |
Date: | 21 Oct 2004 22:31:31 -0400 |
Organization: | Compilers Central |
References: | 04-10-092 |
Keywords: | parse, design |
Posted-Date: | 21 Oct 2004 22:31:31 EDT |
Simple answer: No.
Here's the longer answer.
M Cleary wrote:
> ruby and python use "def"
So does Lisp.
> perl uses "sub"
So does Visual Basic.
> lua uses "function"
So do C, Visual Basic, Pascal and Fortran.
> tcl uses "proc"
So does PL/I.
>
> for example in python you use: def setColor (r, g, b):
>
> I was wondering why that is. I suspect the point is to avoid of ambiguity
> with other language constructs, but I'm not sure.
It's to distinguish between a procedure / function definition and the
call to the proc / func.
> If possible, I don't want to use a keyword. The grammar I want to use
> for my scripting language would go something like this:
>
> func_name '(' param_list ')' IS_TOKEN
> func_body
> END_TOKEN
>
> Does anyone have any suggestions as to whether or not I should have/need a
> keyword in front?
You merely need something which either preceeds or follows one or the
other to differentiate between the two. You have a flag when a
procedure is defined, you have it when it is referenced, or both.
Where I use the word "flag" in this article, I mean a syntactic
element which is used to declare that a symbol which occurred before
or after the syntactic element has certain attributes. The word
"SUBROUTINE" before a definition's name, or an open brace after the
name, would be an example of a flag. So would a two word statement
such as "INTEGER ARRAY" before an identifier would be a flag,
indicating it's an array instead, of course. This may be too obvious
but in view of how complex some of this is I think being just a bit
pedantically obvious is better than leaving something where there is a
possibility of misunderstanding.
The use of a flag on both define of a subroutine and when the subroutine
is called comes from older languages where we did not have good theory
on how to analyze language strings properly, i.e. Fortran, which was
originally created in the late 1950s. Later languages - even COBOL
which first came out only a short time later, eliminated defining a
procedure. You just named it; you called it through PERFORM.
Now as for flagging either at definition or at usage, you can do that
either way, it depends on your taste. You just need to be consistent so
the people writing code and the compilers that read them can understand
what the user means.
For flagging at usage of a procedure, you can require CALL (or PERFORM,
or EXEC or whatever you want to use) before the name when a procedure is
referenced, in which case if you define a procedure you can do so
without any flag. (You'd still need something - again a flag - to show
where the procedure ends, however.)
In the case of functions, an assignment such as A = X(b) would be
either a function call or a reference to an array, so you don't need a
defintion when a function is called, the call itself is implicit
(because if you never define an array called X then it's most likely an
external function).
The problem with defining at call is that procedures are typically
called much more often than they are defined, thus it makes sense from
the principle of least effort to reduce the amount of effort by
requiring definition declaration as opposed to requiring call
declaration. Thus definining at declaration tends to be more popular
with programmers (who are the ones who write compilers and who use them).
Of the languages that still have a declaration to indicate use as an
assignment, it is almost never used. The word "LET" is typically still
available in Basic to indicate an assignment statement. Nobody uses it,
but it's still there (presumably either to support unchanged legacy code
that did use it when it was required, or for the rare and special
occurrence where some (presumably masocistic) programmer uses it for
some (inexplicable) reason). This is why a variable or an array is
defined once and referenced lots of times, as opposed to having to
explicitly state when using a variable or array, because it's less work.
Now, if you flag at the definition of a procedure, you can either flag
before the procedure is named, or after (say an open brace or BEGIN or
IS or some identifier). Again, you still need some kind of flag to
indicate where the procedure or function ends (close brace, END, or some
multi-word flag of your choice).
You can either have a procedure declaration preceeded by a flag to
indicate a definition follows, or you can have a procedure declaration
followed by a flag to indicate the preceding identifier was the start of
a declaration rather than a procedure call (especially important if the
language you are using allows a procedure to be called before it is
defined in the input stream or allows external procedures to be called
without defining them as external.)
As long as the flag cannot legally occur after a procedure call, it will
work to flag following a procedure definition with no preceding flag.
An example is the following in some language using keywords (let's
presume case is not significant):
Sort (Inputfile, outputfile) IS/BEGIN/Defined As/PROC/
...
END/WAS/END DEFINE/PROC END/DONE
or using a symbol
Sort (Inputfile, outputfile) {
...
}
Now, somewhere in the code you have
sort a,b
sort (a,b)
sort inputfile=a, outputfile=b
Or however the call is made.
It is clear that you can tell which is a procedure definition and which
is a call, since the definition flag does not appear. The reason for
predeclaration of identifiers is it makes the compiler writer's job
easier, since otherwise you have to save the identifier and all
arguments until either you get a flag that indicates the start of a
procedure definition, or not (which indicates the start of a procedure
call).
With respect to having the flag follow the definition as opposed to
preceeding it, when the flag comes first, you (as the compiler) know
absolutely. For having the flag follow the identifier, I am reminded of
a help file for a mainframe Star Trek game from twenty years ago
(written in Fortran, no less!) telling how you wouldn't know whether an
enemy you killed was an ordinary Klingon, the Flagship or the Fuel ship
until after you had destroyed it: "Until you kill them, you don't know
who they are." Well, when you have the declaration flag for a procedure
occur after the identifier, until you see the flag (or don't), you (as
the compiler) don't know if it's a define or a call. "Until they flag
them, you don't know which they are."
Paul Robinson
Return to the
comp.compilers page.
Search the
comp.compilers archives again.