General discussions about working with the Astrobe IDE and programming ARM Cortex-M0, M3, M4 and M7 microcontrollers.
-
gray
- Posts: 143
- Joined: Tue Feb 12, 2019 2:59 am
- Location: Mauritius
Post
by gray » Fri May 03, 2019 1:17 pm
From real-world code, distilled down to a test case:
Code: Select all
MODULE M;
IMPORT Main, Out;
TYPE
T = RECORD i: INTEGER END;
T1 = RECORD(T) k: INTEGER END;
R = RECORD t: T1 END;
P = POINTER TO R;
VAR
p: P;
PROCEDURE P2(VAR t: T);
BEGIN
t.i := 13;
Out.String("T"); Out.Ln;
CASE t OF T1:
t.k := 4;
Out.String("T1"); Out.Ln;
END
END P2;
PROCEDURE P1(p: P);
BEGIN
P2(p.t)
END P1;
BEGIN
Out.String("reset"); Out.Ln;
NEW(p);
Out.String("case 1: P2 direct"); Out.Ln;
P2(p.t);
Out.String("case 2: P2 via P1"); Out.Ln;
P1(p)
END M.
This prints:
Code: Select all
reset
case 1: P2 direct
T
T1
case 2: P2 via P1
T
My actual use case is "case 2", and I was baffled that the code within the CASE type test didn't execute. IMHO, both cases should yield the same result (case 1).
What do I miss?
PS: I just realised: still with the M3 7.0 compiler. Maybe 7.0.1 fixes that?
-
cfbsoftware
- Site Admin
- Posts: 525
- Joined: Fri Dec 31, 2010 12:30 pm
-
Contact:
Post
by cfbsoftware » Fri May 03, 2019 11:30 pm
I suspect that this example is an attempt to circumvent
the rule that does not allow type tests on expressions e.g. the following is invalid where p is a record:
Code: Select all
CASE p.t OF T1:
t.k := 4;
Out.String("T1"); Out.Ln;
END
In this context p.t is an expression not a qualified identifier.
If you want to implement your example without any surprises stick to using pointers throughout:
Code: Select all
MODULE M;
IMPORT Main, Out;
TYPE
T = RECORD i: INTEGER END;
PT = POINTER TO T;
T1 = RECORD(T) k: INTEGER END;
PT1 = POINTER TO T1;
R = RECORD t: PT1 END;
PR1 = POINTER TO R;
VAR
p: PR1;
PROCEDURE P2(t: PT);
BEGIN
t.i := 13;
Out.String("T"); Out.Ln;
CASE t OF PT1:
t.k := 4;
Out.String("T1"); Out.Ln;
END
END P2;
PROCEDURE P1(p: PR1);
BEGIN
P2(p.t)
END P1;
BEGIN
Out.String("reset"); Out.Ln;
NEW(p);
NEW(p.t);
Out.String("case 1: P2 direct"); Out.Ln;
P2(p.t);
Out.String("case 2: P2 via P1"); Out.Ln;
P1(p)
END M.
-
gray
- Posts: 143
- Joined: Tue Feb 12, 2019 2:59 am
- Location: Mauritius
Post
by gray » Sat May 04, 2019 3:49 am
Assume P2 is implemented in another module, say implementing T and its extensions (my actual use case); the code is perfectly valid with a qualident as case variable. Now a module client calls P2 "wrongly", and P2 fails silently.
But the test-case should execute correctly with an
IS type test.
Code: Select all
PROCEDURE P2(VAR t: T);
BEGIN
t.i := 13;
Out.String("T"); Out.Ln;
IF t IS T1 THEN
t(T1).k := 4;
Out.String("T1"); Out.Ln
END
END P2;
Same result (OMM, as said, M3 7.0 compiler).
-
cfbsoftware
- Site Admin
- Posts: 525
- Joined: Fri Dec 31, 2010 12:30 pm
-
Contact:
Post
by cfbsoftware » Sat May 04, 2019 5:23 am
There is nothing wrong with procedure P2 in either example. I strongly recommend that you use pointers throughout to minimise confusion, but if you have a compelling reason to pass record elements around as in your example, and want to get your expected result, then you should make the pointer to PI a VAR parameter i.e.
Code: Select all
PROCEDURE P1(VAR p: P);
BEGIN
P2(p.t)
END P1;
-
gray
- Posts: 143
- Joined: Tue Feb 12, 2019 2:59 am
- Location: Mauritius
Post
by gray » Sat May 11, 2019 3:45 am
Thanks, I have changed my code to use pointers now. As you say, it's clearer and cleaner.
Just out of interest, in the case without having the parameter for P1 declared as VAR, shouldn't the compiler flag the call to P2 from P1, as a read-only variable (p.t) is passed to a VAR parameter in P2?
-
cfbsoftware
- Site Admin
- Posts: 525
- Joined: Fri Dec 31, 2010 12:30 pm
-
Contact:
Post
by cfbsoftware » Sat May 11, 2019 4:58 am
The value parameter that is passed to P1 is p, not p.t.
p is pointer. It is not a structured variable, so it is not read-only when it is passed as a value parameter. However, any changes to the value of p (not what it points to) only affect the local copy of the pointer.