Type Test Inconsistency?

General discussions about working with the Astrobe IDE and programming ARM Cortex-M3, M4 and M7 microcontrollers.

Type Test Inconsistency?

Postby 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?
gray
 
Posts: 39
Joined: Tue Feb 12, 2019 2:59 am

Re: Type Test Inconsistency?

Postby 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.
cfbsoftware
Site Admin
 
Posts: 387
Joined: Fri Dec 31, 2010 12:30 pm

Re: Type Test Inconsistency?

Postby 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).
gray
 
Posts: 39
Joined: Tue Feb 12, 2019 2:59 am

Re: Type Test Inconsistency?

Postby 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;
cfbsoftware
Site Admin
 
Posts: 387
Joined: Fri Dec 31, 2010 12:30 pm

Re: Type Test Inconsistency?

Postby 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?
gray
 
Posts: 39
Joined: Tue Feb 12, 2019 2:59 am

Re: Type Test Inconsistency?

Postby 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.
cfbsoftware
Site Admin
 
Posts: 387
Joined: Fri Dec 31, 2010 12:30 pm


Return to Astrobe for ARM Cortex-M3, M4 and M7

cron