gm2
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Gm2] Re: LENGTH() on Solaris 10/sparc


From: Fischlin Andreas
Subject: Re: [Gm2] Re: LENGTH() on Solaris 10/sparc
Date: Mon, 2 Aug 2010 19:54:42 +0000

Dear Gaius,

On 02/Aug/2010, at 12:09 , <address@hidden<mailto:address@hidden>>
 <address@hidden<mailto:address@hidden>> wrote:


M2RTS.Length is use to implement LENGTH when the string is only know at runtime.
For example LENGTH('hello world') is calculated as 11 by the compiler at compile
time whereas:

LENGTH(a)

will expand to a call to M2RTS.Length and be evaluated at runtime.

Fine to be able to let the compiler do LENGTH('hello world') at compile time 
and not to really call a LENGTH procedure. But this does not affect my argument 
that M2RTS.Length is misplaced. It should not be exported from that module.

M2RTS.Length could be implemented as an inlined procedure function
post gm2 1.0, but I thought it easier to debug gm2 by using libraries
where possible.  (This is also how large sets are implemented at present).

perhaps easier to debug because avoiding redunancies, I see that. But making 
modules too interdependent has in my experience always be problematic. A 
trivial procedure such as LENGTH can be safely implemented in many instances 
and the risk to introduce bugs by this redundancy is IMHO nil. ;-) Moreover, 
modules should make sense as functional entitiies. Having M2RTS export a 
trivial string routine such as Length simply makes no sense to me.



Then I can offer some further, more general comments on the design of M2RTS:

I think it is a mistake to offer installation procedures without being able to 
learn about the fact whether the postcondition has been reached or not. The 
routine

PROCEDURE InstallTerminationProcedure (p: PROC) ;

should be defined as

PROCEDURE InstallTerminationProcedure (p: PROC; VAR done: BOOLEAN) ;

ok - I'll change this - probably to use a procedure function returning
TRUE on success.

Excellent


To merely throw an error message is an awful practice at such a low
program level and gives the programmer no means to handle the error
properly. I expect a routine such as InstallTerminationProcedure to
be of the quiet kind. Since TerminationProc are typically installed
by library modules, it is very difficult for the programmer of an
end-user program to debug such a situation unless the library module
programmer handles the error properly.

Then I am missing for sure following procedure being exported from RTMS:

PROCEDURE ExecuteTerminationProcedures;

I'll rename Terminate to ExecuteTerminationProcedures.  Maybe we need
a procedure function to determine whether we are in the Termination
phase as well.

In my understanding not quite the same or not necessary the same. I expect 
Terminate to be a really low level call to the hardware halting the currently 
running process. However, ExecuteTerminationProcedures does nothing of the 
sort. It merely executes all installed termination procedures. A typical 
sequence would then be

ExecuteTerminationProcedures; Terminate;

In particular in a dynamic loader situation, Terminate would merely abort the 
current level and leave the rest of the process stack intact.

The question also arises what is the relationship to HALT. HALT may be the same 
as Terminate, in particular in a single level system as all statically linked 
run-time environments such as that of C are. But as a n implementer you are 
free to also interpret HALT as simply first breaking the program, as any other 
break point set, and allow the user the choice of either calling the debugger 
or perhaps continuing the process if no abnormal condition was encountered or 
to abort the program. Only in the last situation you would then call

ExecuteTerminationProcedures; Terminate;

This would allow to debug the running data/code BEFORE the termination 
procedures have made their garbage collection.


Agreed there is no dynamic module loading possible, since our times
entrench on us the stone age of only static linking and unmodular
programming style, but nevertheless I am not sure whether it would
not be beneficial for having the symmetrical procedures available as
well.

PROCEDURE InstallInitProcedure (p: PROC; VAR done: BOOLEAN) ;
PROCEDURE ExecuteInitProcedures;

sure I'll implement this - the ExecuteInitProcedures will be called by
default just before the main program module BEGIN code.

Exellent and exactly what is needed.


If you wanna see some examples of such a module, based on the
Modula-2 ETH tradition of dynamic linking-loading see our module
DMSystem at
http://se-server.ethz.ch/RAMSES/Objects/DM/DMSystem.html#DMSystem

Then I has a quick look at StrLib and have seen that routine
StrEqual is wrongly implemented and requires two string variables to
have an identical history to succeed. It fails to test for 0C (or
ASCII.nul) presence and needs to be fixed. Here some code replacing
it:

   PROCEDURE SameStrings(VAR (*speed-up*) s1: ARRAY OF CHAR; s2: ARRAY OF 
CHAR): BOOLEAN;
     VAR n1,n2,i: INTEGER; same: BOOLEAN;
   BEGIN (* SameStrings *)
     n1 := HIGH(s1); n2 := HIGH(s2);
     i := 0; same := s1[i] = s2[i];
     WHILE (i<=n1) AND (i<=n2) AND (s1[i]<>0C) AND (s2[i]<>0C) DO
       same := same AND (s1[i] = s2[i]);
       INC(i);
     END(*WHILE*);
     IF (i<=n1) THEN same := same AND (s1[i] = 0C) END(*IF*);
     IF (i<=n2) THEN same := same AND (s2[i] = 0C) END(*IF*);
     RETURN same
   END SameStrings;

or

 PROCEDURE StrEqual (s1,s2: ARRAY OF CHAR): BOOLEAN;
   VAR i,n1,n2: INTEGER;
 BEGIN (* StrEqual *)
   n1 := HIGH(s1); n2 := HIGH(s2);
   i := 0;
   WHILE (i<=n1) AND (i<=n2) AND (s1[i]<>0C) AND (s2[i]<>0C) AND (s1[i]=s2[i]) 
DO
     INC(i)
   END(*WHILE*);
   RETURN (i>n1) OR (i>n2) OR ((i<=n1) AND (s1[i]=0C)) OR ((i<=n2) AND 
(s2[i]=0C))
 END StrEqual;

I believe the StrLib.StrEqual code behaves in the same way as StrEqual
above.  (It uses StrLen to determine the length of the strings under
comparison which handles the ASCII.nul case).  Unless I've
misunderstood something?

You are right, I read this code too quickly. What confused me is the use of the 
variable name Higha. This is in my view very misleading, since a statement like


        Higha := StrLen(a) ;

should rather be written as

lena := StrLen(a) ;

since HIGH and LENGTH have little to do with each other. My problem was just 
the poor variable naming. Thus the code should better be written as



PROCEDURE StrEqual (a, b: ARRAY OF CHAR) : BOOLEAN ;
VAR
   i, lena, lenb: CARDINAL ;
   equal: BOOLEAN ;
BEGIN
   lena := StrLen(a) ;
   lenb := StrLen(b) ;
   IF lena=lenb
   THEN
      equal := TRUE ;
      i := 0 ;
      WHILE equal AND (i<lena) DO
         equal := (a[i]=b[i]) ;
         INC(i)
      END ;
      RETURN( equal )
   ELSE
      RETURN( FALSE )
   END
END StrEqual ;

But above routine is IMHO still not a particularly good one, since it is very 
inefficient. It makes 4 passes through the 2 string variables, while my 
proposals make only the minimum of 2 required and maybe not even those. If the 
two strings differ in the first char, that's first comparison is all what is 
needed and the routine already returns FALSE. Please replace above routine with 
one of mine's. That may quite matter with large string arrays.

Regards,
Andreas


regards,
Gaius




Regards,
Andreas


ETH Zurich
Prof. Dr. Andreas Fischlin
Systems Ecology - Institute of Integrative Biology
CHN E 21.1
Universitaetstrasse 16
8092 Zurich
SWITZERLAND

address@hidden<mailto:address@hidden>
www.sysecol.ethz.ch<http://www.sysecol.ethz.ch>

+41 44 633-6090 phone
+41 44 633-1136 fax
+41 79 221-4657 mobile

            Make it as simple as possible, but distrust it!
________________________________________________________________________



On 25/Jul/2010, at 03:00 , john o goyo wrote:

Andreas:

On 24-Jul-10, at 2:20 PM, Fischlin Andreas wrote:
Hi John,

Sorry, I don't quite get your issue.

On 24/Jul/2010, at 04:27 , john o goyo wrote:
Examination of the failed test cases shows a real oddity.

In a call to LENGTH(s), where s is a string, HIGH(s) is passed as zero and 
LENGTH(s) is always 1.


HIGH(s) is passed as zero has nothing to do with LENGTH(s).
[..]

Perhaps you are actually talking about something else, but then you should 
explain better what kind of oddity you actually mean.

I wrote the above in the context of gm2, specifically, in the context of the 
failed test cases of Length().  I shall elucidate.

In gm2, LENGTH() is defined in terms of Length() under certain circumstances.  
If you read the comment before the function Length() in M2RTS.mod, you will 
find the following.

(*
  Length - returns the length of a string, a. This is called whenever
          the user calls LENGTH and the parameter cannot be calculated
          at compile time.
*)

In the failed test case iso/run/pass/tstLength.mod, the value of LENGTH(s) is 
compared to the value of Length(s), where "s" is an array of characters.  The 
former is converted into a call to the latter and the latter uses HIGH(s) in 
its count.  Unfortunately, as I wrote above, HIGH(s) is zero and consequently 
Length(s) returns 1, hence LENGTH(s) returns 1.

john


_______________________________________________
gm2 mailing list
address@hidden<mailto:address@hidden>
http://lists.nongnu.org/mailman/listinfo/gm2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]