Page 1 of 2

Implementation of SYSTEM.VAL()

Posted: Sun Aug 14, 2016 11:05 pm
by Zorko
David C W Brown wrote:FYI I just tested my example in black box component builder:

Code: Select all

MODULE test;
IMPORT StdLog, SYSTEM;

PROCEDURE Do*;
VAR i,j: INTEGER; l: LONGINT;
BEGIN
i := 1; j := -1;
l := SYSTEM.VAL(LONGINT,i);
StdLog.Int(l); StdLog.Ln
END Do;

END test.
test.Do

And it logs the value '27839728904568833'.

Arghh!

Is anyone proposing that this behaviour is correct?
Surely not?

-- Dave.

Re: Implementation of SYSTEM.VAL()

Posted: Mon Aug 15, 2016 2:20 am
by Ivan Denisov
Yes, it is correct behavior. You are making manipulation with RAM, that is leading to unexpected results.

That is not correct type transformation. If you want to make longint from integer, use just:

Code: Select all

l := i
That this lead to correct type transformation.

Code: Select all

l := LONG(i);
Is also correct.

Re: Implementation of SYSTEM.VAL()

Posted: Mon Aug 15, 2016 9:01 am
by Robert
Zorko wrote:And it logs the value '27839728904568833'.
The hex for "27839728904568833" is "62E81600000001", so the bottom 32 bits are "1" as expected. What the top 32 bits are is undefined in the "Platform Specific Issues" document, and quite likely will vary from one compiler to another. Actually there is no reason to suppose another compiler will have a "SYSTEM.VAL" function.

Re: Implementation of SYSTEM.VAL()

Posted: Mon Aug 15, 2016 11:37 am
by dcwbrown
Thanks. (Obviously) I was not expecting that. Is this documented anywhere?

I ask because I have found no documentation on VAL in any Oberon system beyond the following statement:

VAL(T, x) T, x: any type T x interpreted as of type T

It doesn't say what aspect of x - specifically whether it is the memory beginning where x begins (as I now understand is the case), or the value of x (which I had believed.)
Why would I make this mistake? Because the only place I have found more details is in Wirth's Modula-2 document ETH-3135-01, which says:

VAL(T,x) the value with the ordinal number x and with type T.

So to be clear, Component Pascal's VAL has the same type signature as Modula's, but is almost entirely different.

So
-- Just to confirm - the extreme difference form Modula is intentional, right?
-- Is it specified anywhere that the behaviour as reinterpretation of memory rather than value?

Thanks -- Dave.

Re: Implementation of SYSTEM.VAL()

Posted: Mon Aug 15, 2016 1:52 pm
by Robert
SYSTEM.VAL is documented in "Platform Specific Issues". I have always implicitly understood this as "over-riding type checking", or "reinterpreting memory", rather than as a real type conversion. But it does not say so in as many words!.
Since T & x in "VAL(T,x)" can be any type, not just those known to the compiler writers, I don't know what else it could do.
(This document is specific to the Oms Windows compiler. It does not apply to other operating systems or other compilers.)
Module SYSTEM contains certain procedures that are necessary to implement low-level operations. It is strongly recommended to restrict the use of these features to specific low-level modules, as such modules are inherently non-portable and usually unsafe. SYSTEM is not considered as part of the language Component Pascal proper.
VAL is NOT part of the language Component Pascal, so it is incorrect to say CP defines it differently to ..., as it does not define it at all.

Re: Implementation of SYSTEM.VAL()

Posted: Tue Aug 16, 2016 2:09 pm
by dcwbrown
Thanks for making it clear. That does make sense.
-- Dave.

Re: Implementation of SYSTEM.VAL()

Posted: Sat Aug 20, 2016 10:00 am
by Zorko
Dear all,

We are mentioned a specific feature that may remain unknown to many users.

For SYSTEM.VAL(TYPE, 'value') David proposes to produce a warning when SIZE(TYPE) > SIZE(type of 'value').

Since SYSTEM.VAL works with a value in memory, it may make sense to protect your applications from failure, because SYSTEM.VAL is not intended to access a data address that placed out of a needed 'value'.

Re: Implementation of SYSTEM.VAL()

Posted: Mon Aug 22, 2016 9:53 am
by Josef Templ
Using different sizes would make sense inside an array or record,
i.e. where you have some knowledge about the memory layout.

Re: Implementation of SYSTEM.VAL()

Posted: Mon Aug 22, 2016 2:03 pm
by Zorko
Therefore, I propose to produce warning, and not error. In the case of ignoring this warning, a programmer knows exactly what goes.

Is there a possibility to show a warning in BlackBox?

Re: Implementation of SYSTEM.VAL()

Posted: Mon Aug 22, 2016 7:27 pm
by luowy
Zorko wrote:Therefore, I propose to produce warning, and not error. In the case of ignoring this warning, a programmer knows exactly what goes.

Is there a possibility to show a warning in BlackBox?
yes,you can do it at DevCPB.StPar1

Code: Select all

		| valfn: (*SYSTEM.VAL*)	(* type is changed without considering the byte ordering on the target machine *)
				IF (x.class = Ntype) OR (x.class = Nproc) THEN err(126)
				ELSIF x.typ.comp = DynArr THEN
					IF x.typ.untagged & ((p.typ.comp # DynArr) OR p.typ.untagged) THEN	(* ok *)
					ELSIF (p.typ.comp = DynArr) & (x.typ.n = p.typ.n) THEN
						typ := x.typ;
						WHILE typ.comp = DynArr DO typ := typ.BaseTyp END;
						tp1 := p.typ;
						WHILE tp1.comp = DynArr DO tp1 := tp1.BaseTyp END;
						IF typ.size # tp1.size THEN err(115) END
					ELSE err(115)
					END
				ELSIF p.typ.comp = DynArr THEN err(115)
				ELSIF (x.class = Nconst) & (f = String8) & (p.typ.form = Int32) & (x.conval.intval2 <= 5) THEN
					i := 0; n := 0;
					WHILE i < x.conval.intval2 - 1 DO n := 256 * n + ORD(x.conval.ext[i]); INC(i) END;
					x := NewIntConst(n)
				ELSIF (f IN {Undef, NoTyp, NilTyp}) OR (f IN {String8, String16}) & ~(DevCPM.java IN DevCPM.options) THEN err(111)
				END ;
				IF (x.class = Nconst) & (x.typ = p.typ) THEN	(* ok *)
				ELSIF (x.class >= Nconst) OR ((f IN realSet) # (p.typ.form IN realSet))
						OR (DevCPM.options * {DevCPM.java, DevCPM.allSysVal} # {}) THEN
					t := DevCPT.NewNode(Nmop); t.subcl := val; t.left := x; x := t
				ELSE x.readonly := FALSE; 
					IF p.typ.size>x.typ.size THEN 
						DevCPM.err(-800); (* small than -700  *)
						DevCPM.LogWLn();DevCPM.LogWStr("SYSTEM.VAL(BigSize,SmallSize)") ;DevCPM.LogWLn();
					END;
				END ;
				x.typ := p.typ; p := x
		| movefn: (*SYSTEM.MOVE*)
luowy