What attributes of a programming language simplify its implementation.
1. Simple semantics. That's it. Simple semantics. (Simple meaning
whatever is easy to implement. Not mathematical elegance. Not
consistency.)
sweep any hard semantics under the rug and don't worry about them.
... Label anything that doesn't
work the way you want in your implementation, "undefined behavior".
By the way Richard P Gabriel famously wrote about this, coining the phrase "Worse is better".
it is a classic example of optimizing the wrong thing.
[PL/I was a remarkably good language considering what a rush job it was but it has plenty of odd things, e.g.
DCL (I, J, K) CHAR(3);
I = 1;
J = 2;
K = I+J;
What does K contain? Nope, it contains three spaces because the 1 and 2
are converted to ' 1' and ' 2', they're converted back to integer,
added, converted back to to a default size integer string
like ' 3' and string assignment truncates from the right. -John]
On the other hand, PL/I is pretty good at allowing things, even if
there isn't much reason. I did this one in high school, not knowing
if it would actually work:
DCL (I, J, K, L) CHAR(100);
J='1';
K='100';
L='1';
DO I=J TO K BY L;
PUT LIST(I, SQRT(I));
END;
I suspect no designers of PL/I ever expected someone to try it,
but the ability is there, and compilers do it.
Now, it turns out that you have to add a few blanks to K, as the
loop comparison is done as a string compare. (I didn't guess
that until finding that the loop didn't end.)
C lets you do some things that it probably shouldn't, though.
Unlike many languages, the whole definition of PL/I was written
before writing the first compiler.
(Not that all features were implemented in the first compiler.)
[PL/I was a remarkably good language considering what a rush job it was but it has plenty of odd things, e.g.
DCL (I, J, K) CHAR(3);
I = 1;
J = 2;
K = I+J;
What does K contain? Nope, it contains three spaces because the 1 and 2
are converted to ' 1' and ' 2', they're converted back to integer,
added, converted back to to a default size integer string
like ' 3' and string assignment truncates from the right. -John]
From: "gah4" <gah4@u.washington.edu>
Sent: Sunday, October 02, 2022 11:05 AM
Unlike many languages, the whole definition of PL/I was written
before writing the first compiler.
That's not true. The preprocessor was designed after the first
release. As well as that, some features of output were designed after
the first release.
(Not that all features were implemented in the first compiler.)
[PL/I was a remarkably good language considering what a rush job it
was but
it has plenty of odd things, e.g.
DCL (I, J, K) CHAR(3);
I = 1;
J = 2;
K = I+J;
This will not work either.
In the first place, the lengths of the strings are too small to
accommodate
the converted integer constants, 1 and 2. The STRINGSIZE condition is
raised
at run-time.
In the second place, the length of K is too short to accommodate
the sum of I and J.
In the third place, the STRINGSIZE condition is raised at run-time
for the assignments to I, J, and K.
Apart from that, the compiler gives compile-time messages that,
in each of the three assignments, the string variables are too short to accommodate the values that are to be assigned to them.
What does K contain? Nope, it contains three spaces because the 1 and
2
are converted to ' 1' and ' 2', they're converted back to integer,
added, converted back to to a default size integer string
like ' 3' and string assignment truncates from the right. -John]
Again, not quite. Even if such a program were allowed to run,
the STRINGSIZE condition is raised. What happens after that depends on
what the programmer does to handle the condition.
[The IBM manuals say that STRINGSIZE is normally disabled. So you
can check for truncation if you want, but by default it won't
and you'll get the three spaces. -John]
Yes, STRINGSIZE,** like STRINGRANGE***, SUBSCRIPTRANGE, SIZE,
FIXEDOVERFLOW*, etc
are not enabled by default.
Originally, these were not enabled because it took extra instructions
to implement the test on S/360.
[I agree that adding two numbers and getting three spaces was bad
practice, and there were ways to avoid shooting yourself in the foot.
My point was that there were situations where each individual step was reasonable, but the combination was absurd. Those are hard to
completely avoid. PL/I had a lot of them for entirely understandable
reasons. That didn't mean it was a hard language, rather that you
had to understand what you were doing. -John]
I answered this question on Quora, but I think it is relevant to this community (and I know I'll get discussion as a result)..
What attributes of a programming language simplify its implementation.
1. Simple semantics. That's it. Simple semantics. (Simple meaning
whatever is easy to implement. Not mathematical elegance. Not
consistency.)
How do you get there?
Have a very simple set of types. BASIC had numbers, strings, and arrays. Don't worry about type conversions and floating point versus integer. Sweep that all under the rug.
Whatever your implementation does, that's what it
does. (Even simpler is what a lot of shells do, you have just "strings" and if the strings happen to be a number when you pass them to the "add function", + operator, it does arithmetic. If they aren't it, whatever it does is the definition.)
Christopher F Clark <christoph...@compiler-resources.com> schrieb:
I answered this question on Quora, but I think it is relevant to this community (and I know I'll get discussion as a result)..
What attributes of a programming language simplify its implementation.
...
If ease of language implementation is the primary concern, then
one could use a stack-based language. Easy to write an interpreter
or compiler for, hard to write in the language itself, so it will
likely be very unpopular (but popularity wasn't in the list of
requirements).
Have a very simple set of types. BASIC had numbers, strings, and arrays. Don't worry about type conversions and floating point versus integer. Sweep that all under the rug.You cannot "sweep it under the rug", you have to define the semantics somewhere. It is possible to define the semantics ad-hoc and not to
document them (which you seem to be advocating). That is a recipe
for problems later.
Whatever your implementation does, that's what itThat strikes me as a bad idea if the language is supposed to be
does. (Even simpler is what a lot of shells do, you have just "strings" and if the strings happen to be a number when you pass them to the "add function", + operator, it does arithmetic. If they aren't it, whatever it does is the definition.)
used for something in the real world. Ill-defined semantics are
a disservice to potential users (but not laying traps for the user
was not on the list of requirements, either).
[...]
[Sounds like we're on our way to reinventing Forth. It had (still has) famously tiny implementations. -John]
[...]
[Sounds like we're on our way to reinventing Forth. It had (still has) famously tiny implementations. -John]
Reinventing old wheels is not much fun. But use Forth as your toolbox
to make your own DSL and you can go _very_ far without diving into
all those dragon books and gigabyte compilers and toolsets.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 300 |
Nodes: | 16 (2 / 14) |
Uptime: | 64:23:36 |
Calls: | 6,712 |
Files: | 12,244 |
Messages: | 5,356,124 |