|
From: | Andreas Fischlin |
Subject: | Re: [Gm2] Use of functions in expressions |
Date: | Mon, 17 Nov 2008 00:37:06 +0100 |
User-agent: | Thunderbird 2.0.0.17 (Macintosh/20080914) |
Dear Scott, Thanks for explaining this in more detail. To avoid this story getting too big: The code example you give below has exactly the same problems as the previous one. It is all syntactically illegal in all Modula-2 dialects and all language implementations I know of. In short: You have to rewrite the code to introduce a temporary variable. Moreover, please don't argue this restriction to be an inconsistency in the original language definition. On the contrary, this language property is purposefully and carefully designed that way. That definition avoids syntax difficulties and compiler building difficulties, in particular with code generation. Arguing that some other languages might offer similar features as you seem to be interested in, is not particularly helpful either, since those languages may be based on very different language philosophies. What you try to accomplish, is simply not possible in Modula-2. If you fear to have to make too many changes while porting existing code to gm2, asking for such features as you seem to imply, i.e. dialect introduction, is IMHO not the way to go. We should for good reasons stick to the language syntax as carefully designed. If the former is your concern, I'd rather consider to program a code translation assistant, if you have hundreds of such constructs. tcl commands such as regsub, available from within AlphaX (http://alphatcl.sourceforge.net/wiki/) might be a solution. Or a Modula-2 program similar to the cross-reference generator you find in PIM (PIM2, p. 87-92, section 25 "Program decomposition into modules") or parts from a compiler. We have done both successfully (XREF in RAMSES Extras http://www.sysecol.ethz.ch/SimSoftware/SimSoftware.html#RAMSES_Extras). Even if such an assistant gives you only a partial solution that requires additional manual editing, it can already safe you lots of time. Such a translation assistant may generate a temporary variable declaration at the wrong place in the code. But if it is already generated, translation becomes much easier, since you need only to move the declaration to the proper place, not write it from scratch. Modula-2 compilers will help you to avoid any mistakes, since forgetting about any such move will be picked by the compiler and you learn about it already at compile time. Regards, Andreas Cited References: ---------------------- PIM2: Wirth, N., 1983 (2 (corr.) ed.). Programming in Modula-2. Springer-Verlag: Berlin a.o, 176 pp. Scott Robinson wrote: Hi Andreas, I apologize for not explaining the situation thoroughly so I'll do so now. I have some existing Modula-2 code that was built with an internal version of a Modula-2 compiler (the compiler was never sold as a separate product). I would like to run that code through gm2 since it will allow me to port the code to a different architecture...hopefully with minimal effort. It will also be an excellent test for the gm2 compiler. The main problem is that this internal Modula-2 compiler has some non-standard enhancements so whenever I run into something that doesn't compile through gm2 I have to figure out if it is a problem with the gm2 parser (which is a beta) or if it is a problem with the original Modula-2 code being non-standard. Hopefully that explains the questions I am posting to the list since I don't have access to either the ISO Modula-2 standard or other production Modula-2 compilers. Now to answer your particular points: I'm not particularly interested in arguing the pros and cons of the ISO Modula-2 standard especially since I don't have access to it :-). However, it is a standard so I am assuming that Gaius is at least designing the gm2 parser to accept language constructs accepted by that standard as opposed to restricting it to Wirth (1983). Hopefully if there are production compilers out there that accept non-standard language constructs Gaius is at least considering inclusion of those constructs otherwise there would be porting difficulties moving existing Modula-2 code from those compilers to gm2. In regards to my example, evidently it wasn't acceptable so I'll try a different one with a function returning a pointer instead: MODULE test1; FROM InOut IMPORT WriteString, WriteCard, WriteLn; TYPE tItemPtr = POINTER TO tItemNode; tItemNode = RECORD key : CARDINAL; value : CARDINAL END; tListPtr = POINTER TO tListNode; tListNode = RECORD item : tItemPtr; next : tListPtr END; PROCEDURE FindItem(list : tListPtr; key : CARDINAL) : tItemPtr; BEGIN (* Empty to make this shorter *) RETURN NIL END FindItem; VAR list : tListPtr; BEGIN (* Code to build the list here *) (* Attempting to dereference a pointer '^' returned by a function within an _expression_ results in a compile failure. *) WriteString("The value with key 3 is "); WriteCard(FindItem(list, 3)^.value, 1); WriteLn; (* Code to destroy the list here *) END test1. The gm2 compiler gives the following error when compiling the above example: #gm2 -c test1.mod test1.mod:36:3: error: syntax error, found `^' test1.mod:36:3: error: syntax error, `)' missing test1.mod:36:3: error: syntax error, `END' missing test1.mod:36:3: error: inconsistant program module name test1.mod:36:3: error: syntax error, `.' missing test1.mod:36:3: error: syntax error, found `,' test1.mod:42:1: error: compilation failed Because of the above error, I would have to store the function result into a temporary variable and then do the pointer dereference using the temporary. Thus a function returning a POINTER has inconsistent behavior versus a function returning a REAL, INTEGER, or CARDINAL...all of which can be used immediately in the _expression_ without storing into a temporary first. My opinion is that that inconsistency is a design flaw in the Modula-2 language definition as specified in Wirth (1983) and I am wondering if the ISO Modula-2 standard fixed the inconsistency by allowing the above syntax? I am also interested if any other Modula-2 compilers accept it? Your suggestions on how to change the code aren't relevant (to me anyways) since I have no intention of going to that much effort to port the code to gm2. You asked "why do I want to have string expressions?" Well, to get a specific character out of it would be one reason. Other languages treat strings as first class data types and have quite a few operations defined on them (length, replication, splicing, concatenation, etc). All of those make perfect sense to use on a string in an _expression_. Those BNF diagrams you are pointing me to are derived from Wirth (1983) and not the ISO Modula-2 standard (see http://cui.unige.ch/db-research/Enseignement/analyseinfo/Modula2/) so they do not provide the information I am after. Thanks, Scott Cited references: -------------------- Wirth, N., 1983 (2 (corr.) ed.). Programming in Modula-2. Springer-Verlag: Berlin a.o, 176 pp. On Sun, Nov 16, 2008 at 9:12 AM, Andreas Fischlin <address@hidden> wrote:Hi Scott, Exactly because of such rather messy code did Wirth in his original language defintion NOT allow for such constructs. That some compilers accept such code is actually only due to the ISO standard of Modula-2. Prior to this your first formulation was not legal either and since I am not an adept with the ISO standard, I have no strong opinions about the pros and cons of this ISO extension of the original Modula-2. I'm wary it might complicate matters unnecessarily, something fundamentally at odds with Modual-2. Remember also that the ISO standard is not without difficulties, which makes people like me rather sceptical with respect to its benefits, except for settling on a standard library (but that has little to do with the language itself). In this context see also 10 little Modulans... http://www.scifac.ru.ac.za/cspt/sc22wg13.htm#Ten . More specifically: First, please note that I see very little reason to write in Modula-2 such code as you wrote. Function procedures should be used only if they return a well defined object, e.g. a real variable, if they have no side effects and if they can be used in place of a variable in an _expression_ (e.g. think of it as a factor http://cui.unige.ch/db-research/Enseignement/analyseinfo/Modula2/factor.html). Therefore my first question to you whould be: Why do you want to have string expressions? Unless you would have some applications where you really want to multiply a string meaningfully with a number - or something similarly exotic - I see little sense in that. Modula-2 is helping you to stay away from such applications. Conclusion: use a procedure, NOT a function procedure. Second, when you comment some code by "this works", "this does not work" then it is not clear what you mean from that. You should in general always distinguish between, code that can be compiled, because the compiler accepts it as legal, or whether the code does fail during execution, typically causing a run-time error. From what you write further down I guess that you mean "can be compiled" vs. "can't be compiled". Thirdly, Write(tester()[4]); is a phantasy code clearly in conflict with any Modula-2 syntax I know of. It conflicts with the BNF for a procedure call (see http://cui.unige.ch/db-research/Enseignement/analyseinfo/Modula2/procedure_call.html). Therefore any Modula-2 compiler should reject it as syntactically wrong. A correct solution to what you try to do would be: PROCEDURE Tester(VAR s: ARRAY OF CHAR); BEGIN Assign("testing",s); END Tester; BEGIN Tester(temp); WriteString(temp); ... That is all not very complicated and IMHO quite elegant code. Why trying something different that gives you and compiler builders only trouble? I recommend you give up on your idea of using a function procedure in relation with strings as illustrated above. Of course, there are some rather rare cases in which it may make sense to work with function procedures with respect to strings. E.g. if such a function returns an opaque string object or a single CHAR. See this module from the 'Dialog Machine' for such procedures: http://se-server.ethz.ch/RAMSES/Objects/DM/DMStrings.html#DMStrings (with Comments) http://se-server.ethz.ch/RAMSES/Objects/DM/DM_Quick_Reference.html#DMStrings (without Comments) The case of a single CHAR may be interesting in a conversion function such as PROCEDURE Upper(ch: CHAR): CHAR; BEGIN RETURN CAP(ch) (* should of course be something more meaningful *) END Upper; and its application PROCEDURE StringToUpper(VAR s: ARRAY OF CHAR); VAR i,n: INTEGER; BEGIN n := HIGH(s); WHILE (i<=n) AND (s[i]<>0C) DO s[i] := Upper(s[i]); INC(i) END; END StringToUpper; all not very useful, but I hope illustrative. In general, please note also, Modula-2 is NOT C and arrays, including strings, should be considered what they are, a structured data type that has first of all nothing to do with dynamic data as passed by function procedures via the stack or pointers referencing data in the heap. An array is a static data structure with a finite size allocated by the compiler at compile time. It faciliates repetitive operation on its element, which, BTW, can be very complex, i.e. it can be an entire RECORD of a very complex type. Hope this helps to solve your problems. Sincerely yours, Andreas Fischlin Scott Robinson wrote: Hi all, I have another Modula-2 language question about function results and using them in expressions. Specifically, it seems that the language allows you to return an array or a pointer but apparently (at least according to the GM2 compiler) does not allow you to turn around and use an array subscript to access a particular element of the array within an _expression_. The pointer dereference operator '^' also appears to be illegal after a call to a function. A specific example: MODULE test1; FROM InOut IMPORT WriteString, Write, WriteLn; TYPE tArr = ARRAY [0..9] OF CHAR; VAR temp : tArr; PROCEDURE tester() : tArr; BEGIN RETURN "testing"; END tester; BEGIN (* This works *) WriteString("The 5th character returned is "); temp := tester(); Write(temp[4]); WriteLn; (* This does not work *) WriteString("The 5th character returned is "); Write(tester()[4]); WriteLn; END test1. GM2 gives the following for the above: # gm2 -c test1.mod test1.mod:26:3: error: syntax error, found `[' test1.mod:30:1: error: compilation failed I'm wondering if the Modula-2 ISO standard specifically disallows that syntax? And, if anyone has access to other Modula-2 compilers, do those compilers accept the above? Thanks, Scott _______________________________________________ gm2 mailing list address@hidden http://lists.nongnu.org/mailman/listinfo/gm2 -- ________________________________________________________________________ Dr. Andreas Fischlin, Ph.D., Group Director Terrestrial Systems Ecology Institute of Integrative Biology: Ecology, Evolution, Infectious Disease Department of Environmental Sciences, ETH Zurich Address: ETH Zurich, CHN E21.1 8092 Zurich, Switzerland Phone: +41 44 633-6090 / Fax: +41 44 633-1136 http://www.sysecol.ethz.ch/Staff/af/ http://www.sysecol.ethz.ch/ _/_/_/ _/_/_/ _/ _/ _/ _/ _/ _/ Eidgenoessische Technische Hochschule Zuerich _/_/_/ _/ _/_/_/ Swiss Federal Institute of Technology Zurich _/ _/ _/ _/ Ecole polytechnique federale de Zurich _/_/_/ _/ _/ _/ Politecnico federale de Zurigo Make it as simple as possible, but distrust it! ________________________________________________________________________ --
________________________________________________________________________ Dr. Andreas Fischlin, Ph.D., Group Director Terrestrial Systems Ecology Institute of Integrative Biology: Ecology, Evolution, Infectious Disease Department of Environmental Sciences, ETH Zurich Address: ETH Zurich, CHN E21.1 8092 Zurich, Switzerland Phone: +41 44 633-6090 / Fax: +41 44 633-1136 http://www.sysecol.ethz.ch/Staff/af/ http://www.sysecol.ethz.ch/ _/_/_/ _/_/_/ _/ _/ _/ _/ _/ _/ Eidgenoessische Technische Hochschule Zuerich _/_/_/ _/ _/_/_/ Swiss Federal Institute of Technology Zurich _/ _/ _/ _/ Ecole polytechnique federale de Zurich _/_/_/ _/ _/ _/ Politecnico federale de Zurigo Make it as simple as possible, but distrust it! ________________________________________________________________________ |
[Prev in Thread] | Current Thread | [Next in Thread] |