Expression evaluation

This forum is for any questions about the language Tutorial D or the Rel implementation of it.
Post Reply
Chris Walton
Posts: 76
Joined: Sat Aug 18, 2012 2:13 pm

Expression evaluation

Post by Chris Walton »

I am puzzled by the action of the type system in some respects and am seeking clarification. If you think this query would be better directed to Hugh Darwen, I will submit it on the TTM list.

I have defined two types, one inheriting from the other, and one operator on the parent type as follows:

Code: Select all

TYPE unbounded_integer
  POSSREP {VALUE CHAR CONSTRAINT 
    (CAST_AS_INTEGER(VALUE) > 0) OR 
    (CAST_AS_INTEGER(VALUE) <= 0) OR 
    VALUE = "unbounded"};

Code: Select all

TYPE non_negative_ub_integer IS {
  unbounded_integer CONSTRAINT   
    (CAST_AS_INTEGER(THE_VALUE(unbounded_integer)) >= 0) OR 
    THE_VALUE(unbounded_integer) = "unbounded"
  POSSREP{X = THE_VALUE(unbounded_integer)}};
Definition of these types automatically generates the operator:

Code: Select all

unbounded_integer(CHARACTER) RETURNS unbounded_integer
There is no comparable operator generated for the child type.

Code: Select all

OPERATOR greater_than(P unbounded_integer, Q unbounded_integer) RETURNS BOOLEAN;
  CASE;
    WHEN Q = unbounded_integer("unbounded") THEN return FALSE;
    WHEN P = unbounded_integer("unbounded") AND Q <> unbounded_integer("unbounded")
      THEN return TRUE;
  ELSE return 
   (CAST_AS_INTEGER(THE_VALUE(P)) > CAST_AS_INTEGER(THE_VALUE(Q)));
  END CASE;
END OPERATOR;
if the following is entered at the command line of DBrowser,

Code: Select all

greater_than(unbounded_integer("1"),unbounded_integer("1"))
then the response is:

Code: Select all

non_negative_ub_integer("1")
This makes no sense at all to me - while the expression has been defined in terms of the parent type, and the values concerned do meet the constraints of the child type, why should an operator on a parent type return the child type?
Dave
Site Admin
Posts: 372
Joined: Sun Nov 27, 2005 7:19 pm

Re: Expression evaluation

Post by Dave »

The definition of a CONSTRAINT in the subtype means you're using subtyping-by-constraint (sometimes shorted to "S-by-C"). Therefore, if you select a value of the supertype and a constraint is satisfied in a subtype, then the constraint is stating that the value is of the subtype. Hence, when you select an unbounded_integer("1") that meets the constraint of a non_negative_ub_integer, the constraint states that it is a non_negative_ub_integer, and it tells you so by returning non_negative_ub_integer("1").
Chris Walton
Posts: 76
Joined: Sat Aug 18, 2012 2:13 pm

Re: Expression evaluation

Post by Chris Walton »

So what if there are more than one subtype; with overlapping constraints such as (an addition to my previous example):

Code: Select all

TYPE positive_ub_integer IS {
  unbounded_integer CONSTRAINT   
    ( CAST_AS_INTEGER ( THE_VALUE ( unbounded_integer ) ) > 0 ) OR 
    THE_VALUE( unbounded_integer ) = "unbounded"
  POSSREP { X = THE_VALUE ( unbounded_integer ) } };
How is the returned type chosen?

Does your response imply that if one has a S-by-C that a value is a supertype only if it meets none of the constraints of its subtypes? You stated "the constraint is stating that the value is of the subtype" (your emphasis). I have been taking a description of a subtype as implying that, by definition , it must meet the constraint, but does not impose any limitation on something declared as the supertype.

Alternatively, is the inheritance model, when using S-by-C, assuming that the supertype is only meaningful when it meets the constraints of one of its subtypes?
Dave
Site Admin
Posts: 372
Joined: Sun Nov 27, 2005 7:19 pm

Re: Expression evaluation

Post by Dave »

Chris Walton wrote:So what if there are more than one subtype; with overlapping constraints [...]
How is the returned type chosen?
It's chosen arbitrarily. Constraints should be designed so they're not overlapping.
Chris Walton wrote:Does your response imply that if one has a S-by-C that a value is a supertype only if it meets none of the constraints of its subtypes?
That is correct. The most specific type of a value is the supertype if and only if it meets none of the constraints of its subtypes.

Perhaps the following example will be helpful. Given the following:

Code: Select all

TYPE basetype POSSREP {x INTEGER};  

TYPE derivedtype1 IS {basetype 
   CONSTRAINT THE_x(basetype) >= 4 AND THE_x(basetype) <= 7 
   POSSREP {y = THE_x(basetype)}}; 

TYPE derivedtype2 IS {basetype 
   CONSTRAINT THE_x(basetype) >= 2 AND THE_x(basetype) <= 5 
   POSSREP {y = THE_x(basetype)}};
The above defines derivedtype1 as being basetype(4) to basetype(7), whilst derivedtype2 is basetype(2) to basetype(5), so they overlap.

Below shows a set of selector expressions followed by the resulting value:

basetype(1)
basetype(1)

basetype(2)
derivedtype2(2)

basetype(3)
derivedtype2(3)

basetype(4)
derivedtype2(4)

basetype(5)
derivedtype2(5)

basetype(6)
derivedtype1(6)

basetype(7)
derivedtype1(7)

basetype(8)
basetype(8)

basetype(9)
basetype(9)
Chris Walton
Posts: 76
Joined: Sat Aug 18, 2012 2:13 pm

Re: Expression evaluation

Post by Chris Walton »

Prior to your response, I was rechecking "Inheritance Model". My issue arises from section 10 of that document. For the first time using Rel/Tutorial D, I feel I disagree with a design point of the language, rather than merely failing to understand the syntax. As a consequence I will raise this issue on the TTM list (or at least point out the existence of this thread). However, there are still other points arising from this example, spelled out below.

I believe that section 10 of the document describes a necessary, but not sufficient definition of subtyping by specialisation constraint. The missing piece is an amendment so that it reads:
that a value shall be of type T' if and only if it is of type T, it satisfies constraint SC, and is defined (or assigned) as being of type T' or one of its subtypes.
This would permit overlapping constraints, and would prohibit a value changing type just because it happens to meet a constraint on one of its subtypes. I believe the example we have been discussing shows a justification for this change. I set out below section 10 together with my proposed amendment.

While making this suggestion, I do want to check that I am not missing a capability of the language that would enable me to define data types with overlapping constraints without generating an effective change of type from supertype to subtype if it happens that constraints defined elsewhere are met. In addition to the major design point about type inheritance, there is a minor syntactical query hidden in my example. Why does

Code: Select all

greater_than(unbounded_integer("1"),unbounded_integer("1"))
not return a boolean value of false?
Section 10
Let T be a regular type (see IM Prescription 20) and hence, necessarily, a scalar type, and let T' be a nonempty immediate subtype of T. Then the definition of T' shall specify a specialization constraint SC, formulated in terms of T, such that a value shall be of type T' if and only if it is of type T and it satisfies constraint SC. ...
Section 10 amended
Let T be a regular type (see IM Prescription 20) and hence, necessarily, a scalar type, and let T' be a nonempty immediate subtype of T. Then the definition of T' shall specify a specialization constraint SC, formulated in terms of T, such that a value shall be of type T' if and only if it is of type T, it satisfies constraint SC, and is defined (or assigned) as being of type T' or one of its subtypes. ...
Post Reply