Path: utzoo!mnetor!uunet!lll-winken!lll-lcc!lll-tis!ptsfa!ihnp4!ihlpf!nevin1 From: nevin1@ihlpf.ATT.COM (00704a-Liber) Newsgroups: comp.lang.misc Subject: Re: Languages and learning (was: Philosophy of C) Message-ID: <3579@ihlpf.ATT.COM> Date: 2 Feb 88 02:37:06 GMT References: <11348@brl-adm.ARPA> <3473@ihlpf.ATT.COM> <3487@ihlpf.ATT.COM> <3555@ihlpf.ATT.COM> <670@l.cc.purdue.edu> Reply-To: nevin1@ihlpf.UUCP (00704a-Liber,N.J.) Organization: AT&T Bell Laboratories - Naperville, Illinois Lines: 167 In article <670@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes: . .Most assembly languages are prenex, that is, the instruction comes first. This .is what makes assembly difficult to read and write. The assembler language, .COMPASS, on the CDC6x00 and the related CYBERs, is slightly prenex in that .the class of the instruction (integer, floating, "double", Boolean, increment, .etc.) is prenex, and the rest is mainly infix, although "," separators are .sometimes used. I have used this language extensively. The assembly .language on the CRAYs, CAL, uses very little of the prenex form, but .requires that the class of the operator be included. It is also rather .artificial in many places. (CYBER--isn't that the machine that used 56 bit words? :-)) Looking at a variety of assembly languages (68k, Z80, PDP11), it looks like most of the operators where infix would be applicable would become augmented assignment operators, which I find a lot harder to read than prenex form. If augmented operators are not used, then the LHS of the assignment must be repeated exactly as the first item of the RHS of the expression: ex: PDP-11 ADD (R0), (R0)+ ;add what R0 points to to itself and inc R0 non-augmented: (R0) = (R0) + (R0)+ ;and remember, the inc is done after ;assignment; also, this 'addition' is ;not commutative. augmented: (R0) += (R0)+ ;harder to read than original .Here is the place that the advocates of the present clumsy assemblers fail to .see the possibilities. A given location, either register or memory, is a .collection of bits. How the collection will be used is, indeed, up to the .programmer. Now in HLLs we _declare_ the "type" assigned to that location. .Some languages, unfortunately, require that the type be inviolable; this is .generally called strong typing. Some languages provide inadequate means of .allowing the programmer to change the type of something in memory; it is .extremely difficult for the user to change the type of something in registers. . .What I am proposing is that an argument, either operand or result, recognizable .by machine operations be typable by the user. Then if the types of the .arguments are compatible with a version of the operator, that version is .used. Thus on the VAX there are numerous move and convert instruction; .most of them would become . . X = Y . .In some there can be a modification of the instruction, such as complementing .or negating, or restrictions can be put on sign extension, etc. This would be .done by modifying the "=". Only if we wish to perform a version of the move .which is not appropriate for the types of X and Y would the type symbols be .affixed to the "=" or its augmentation. This would then become an explicit .unoverloading of the operation, while permitting normal overloading. Notice .that typing would, in general, be required of all arguments. Looking at the .VAX instructions with this in mind, I found 16 types, some of which may be .represented by disconnected pieces of storage (register or memory). . .Clearly the programmer must be able to change the type of an entity at will. .This is not the cast operation in C; it is rather a _use_ operation. The .meaning is either that the old type is no longer in use, which can with .difficulty be implemented in the present HLLs, or else it can be a statement .to the system, "I know you do not understand what I am doing, but remember .that you are supposed to do what I tell you." First off, changing all the MOV statements to 'X = Y' do have reprocussions: the language would have to be 'compiled', not 'assembled', since I no longer know what statements are actually being executed. If I need to do time-sensitive operations, your language is out because I need to get to the hardware instructions (but assembler is supposed to represent 1:1 the hardware instructions). Your 'do what I tell you' statement means to me: now I want to program in assembler and not this pseudo slightly higher level language. To do any real assembler work, you HAVE to turn on your 'do what I tell you' switch. On register machines most operations are done in registers. In order to implement your suggestion, registers would have to be typed (although the type can be changed). The typing restrictions cannot always be enforced, due to branching and/or jumping to calculated locations or even jumping into the operand of an instruction (this is frowned upon but possible). .I am not "mucking it up," unless you are committed to operation-space- .comma separated argument list. I have already pointed out that there are .assemblers not in this form. If you append the type symbols to the operation .symbols, this is essentially the CAL syntax. I see no reason why someone .programming with the full set of machine instructions need be perturbed by .infix notation, already used by some assemblers, and overloaded operators. .I would object to not allowing the programmer to include the type symbols, .as this would run into the weaknesses of strongly typed languages. It is easier to me to use ADDB, ADDW, and ADDL to mean the byte, word, and long adds, respectively, than to augment the already augmented assignment operators. I find it much easier to read and easier to find bugs (especially when you have code that jumps around all over the place). If the architecture lends itself to infix operators, then use them. But do not claim that they are better than prenex operators for all assembly languages. .I admit it would be difficult for a _disassembler_ to have any of the .flexibility I would like--it might even be desirable for a disassembler .to _always_ specify the types. This is because you want an uncompiler, not a disassembler. You have defined a language which is a level above assembler. This is like trying to convert from assembler to Pascal; a very difficult task, at best. .> >> One of the major habits is un-structured programming. .> > .> >I can give you examples where GOTOs are the simple thing to do, and the .> >"structured" alternatives are much more complex. Structured programming .> >can block thinking of the efficient way to do things. .> .> Please post some examples of problems (not solutions that are already .> implemented using GOTOs) where structured alternatives are 'much more' complex. . .Of course, we can always replace a GOTO by "if TRUE then ..." Notice the word ._efficient_ in my previous posting. Suppose (and this is an actual case) we I noted the word. What do you mean by 'efficient'? (I have deleted your example since I have not had time to look at it. I will comment on it later.) .I know of no hardware which does not internally use GOTOs. There are hardware .implementations of conditional transfers on some machines which will make a .simple test in the transfer instruction, but in nanocode this is: make the .test; then transfer if the test succeeds (fails). In other words, the machine .must have an internal GOTO. If we want to understand the machine, we must, .therefore, have GOTO. Yes, but do you really need to know that in your first programming language (the original topic of this discussion)? It is very hard to learn structured programming after using GOTO, since attacking a problem via a structured method usually requires a different way of looking at it. And GOTO can be understood by looking at a block diagram of how a WHILE loop works. Need you actually be able to use a GOTO statement in order to understand how it works? I would rather see someone go from a structured environment to using branching than the other way around. A side comment: The structure that Pascal imposes is far too rigid. C statements like 'break', 'continue', and 'return' are necessary; otherwise, far too much time is spent trying to make algorithms 'fall off the end'. .This is exactly why teaching HLL first is bad. The student gets the impression .that the machine behaves like the HLL. Only a badly designed machine has an .if...then...else structure. Machines have operations of varying complexity; .the student who gets the impression that the structure of the machine looks .like the HLL certainly has a lot to unlearn! With the possible exception of programming on a PC, most of the 'controlling of the hardware' is done via macros and system calls. What's the difference whether I make the calls from assembler or C; I am still faced with the same restrictions. I don't get the 'feel' of the machine since all I am doing is telling some other routine to go do the hardware stuff for me. Your if-then-else statement: By your statement most machines are badly designed since most contain conditional branching statements; ie, IF certain flags are set/reset THEN branch somewhere ELSE go on to the next statement. Even if it can be concluded that learning assembler first is better (a conclusion I do not believe in), your language (what you think assembler should be) also detracts from how the machine really work; ie, machine memory locations don't really have type, etc. I do not believe that, when first learning how to program, that many people believe that their machine acts just like their HLL program. They consider 'write()' statements in Pascal, for instance, to be 'black boxes' that put their output on the screen. There is no need to initially know what is in that black box in order to use it. When the programming concepts, such as structure, are already laid down, then it is time to learn to program in assembler; the benefits far outway the drawbacks. -- _ __ NEVIN J. LIBER ..!ihnp4!ihlpf!nevin1 (312) 510-6194 ' ) ) "The secret compartment of my ring I fill / / _ , __o ____ with an Underdog super-energy pill." / (_