[Top][All Lists]
[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