• Ingen resultater fundet

Type Definitions

2.3 Types in RSL

2.3.3 Type Definitions

Operator Translation

RSLMap<K,V>union(RSLMap<K,V>)

RSLMap<K,V>override(RSLMap<K,V>)

\ RSLMap<K,V>restrictBy(RSLSet<K>)

/ RSLMap<K,V>restrictTo(RSLSet<K>)

RSLMap compose(RSLMap)a

dom RSLSet<K>dom()

rng RSLSet<V>rng()

a The missing generic types is due to the involvement of three types: the key of the inner map, the value of the inner map which is the same as the key of the outer map, and the value of the outer map. Use of more generic types in a method than defined in the class signature is not permitted in Java 1.5.

Table 2.9: Overview of translation of RSL map operators into Java.

The use of the operators and their translations are shown in Example 2.22

Example 2.22 Use of map operators.

[ 17→1.0,27→2.0 ] ∪[ 37→3.0, 47→4.0 ] [ 17→1.0,27→2.0 ] †[ 17→3.0 ]

[ 17→1.0,27→2.0 ] \ {2}

[ 17→1.0,27→2.0 ] /{1}

[ 17→1.0,27→2.0 ] [ 1.07→

``

one00]

dom [ 17→1.0,27→2.0 ] rng [ 17→1.0,27→2.0 ]

new RSLMapDefault<I n t e g e r , Double>(new I n t e g e r [ ]{1 , 2},

new Double [ ]{1 . 0 , 2 . 0}) . union ( new RSLMapDefault<I n t e g e r , Double>(new I n t e g e r [ ]{3 , 4},

new Double [ ]{3 . 0 , 4 . 0}) ; new RSLMapDefault<I n t e g e r , Double>(new I n t e g e r [ ]{1 , 2},

new Double [ ]{1 . 0 , 2 . 0}) . o v e r r i d e (

new RSLMapDefault<I n t e g e r , Double>(new I n t e g e r [ ]{1}, new Double [ ]{3 . 0}) ; new RSLMapDefault<I n t e g e r , Double>(new I n t e g e r [ ]{1 , 2},

new Double [ ]{1 . 0 , 2 . 0}) . r e s t r i c t i o n B y (new RSLSetDefault<I n t e g e r>(2) ;

new RSLMapDefault<I n t e g e r , Double>(new I n t e g e r [ ]{1 , 2}, new Double [ ]{1 . 0 , 2 . 0}) . r e s t r i c t i o n T o (new RSLSetDefault<I n t e g e r>(1) ;

new RSLMapDefault<I n t e g e r , Double>(new I n t e g e r [ ]{1 , 2}, new Double [ ]{1 . 0 , 2 . 0}) .

compose ( new RSLMapDefault<Double , S t r i n g>( 1 . 0 , ” one ” ) ; new RSLMapDefault<I n t e g e r , Double>(new I n t e g e r [ ]{1 , 2},

new Double [ ]{1 . 0 , 2 . 0}) . dom ( ) ; new RSLMapDefault<I n t e g e r , Double>(new I n t e g e r [ ]{1 , 2},

new Double [ ]{1 . 0 , 2 . 0}) . rng ( ) ;

types are considered to be equivalent if the names of the types are the same.

In Java, it is possible to create new types containing the same components, and then name them differently. However, it is not possible to assign a value of one of these types to a variable of another type. The two types in Java are different types, whereas in RSL, the two types are the same. There are two possible strategies for solving this.

Example 2.23 Structural equivalence in RSL schemePRODUCT TEST =

class type

Product 1 = Int× Real, Product 2 = Int× Real variable

p 1 : Product 1 := (1, 1.0), p 2 : Product 2 := (2, 2.0) value

test : Unit → read p 1 write p 2 Unit test() ≡

p 2 := p 1 end

The first strategy is to invent a naming convention and use this for all abbreviation types defined in RSL, thereby ensuring that all equivalent ab-breviations are translated as one type in Java.

The second strategy is to let both abbreviation types be created with the names given, and then ensure by other means that it is possible to assign a variable of one type to a variable of another type. One way to ensure this is to create a common super type and then let variables which are defined be of the super type, rather than one of the specific types.

Both strategies have the drawback, that the translation is quite different from the specification. The first solution is chosen since it provides the code with the least number of classes. The tool carrying out the translation should create a class named with an underscore and the content of the type expression seperated by underscore. The Product 1 type abbreviation in Example 2.23 should result in a Java class: Int Real.

Sort Definition

A sort definition specifies a type which has yet to be defined. The sort type can be used in type expressions, e.g. in other type definitions. The transla-tion of the sort type should have the same properties. The translatransla-tion of the sort definition is an empty class, because this resembles the same properties.

The translation from RSL into Java is as follows:

RSL:

type t Java:

public c l a s s T { }

Where T is the translation of the name t.

Variant Definitions

A variant definition is a convenient way to group a number of values and functions on sort definitions [11]. A variant definition is a grouping of alter-natives, which may either be constants or record constructors with compo-nents defining the content of the alternative. The types may be recursively defined.

In the translation into Java, the same properties are desired. There is a need for a type which is a grouping of alternatives. There is only one concept in Java which allows for values of different types to be assigned to the same variable, and that is if the types in Java are subtypes of a general type, and that the variable is of the general type.

A variant definition is translated as an abstract class with one extending class for each alternative.

The translation from RSL into Java is as follows:

RSL:

type t1 == a1 | . . .| an

Java:

public abstract c l a s s T1 {

public abstract boolean e q u a l s ( Object o ) ; public abstract S t r i n g t o S t r i n g ( ) ;

}

public c l a s s A1 extends T1 {. . .} public c l a s s An extends T1 {. . .}

T1 is the translation of the name t1. A1 is the translation of the name a1. An is the translation of the name an. Translation of a constant alternative:

RSL:

typet == a Java:

public c l a s s A extends T

public boolean e q u a l s ( Object o ) { i f( o instanceof A)

return true; e l s e

return f a l s e; }

public S t r i n g t o S t r i n g ( ) { return ”A” ;

} }

T is the translation of the name t.

A is the translation of the name a.

The reason for the special implementation of the equals method in the class A, is that whenever an A object is created, it should be identical to other objects of the type. This could also be achieved by implementing the singleton design pattern [7]. This solution, however, would lead to two different ways of creating objects, because objects are created by methods and not constructors in the singleton design pattern.

Translation of a record constructor alternative:

RSL:

typet = a(t2) Java:

public c l a s s A extends T { public T2 v 1 ;

public A ( T2 v 1 ) { t h i s. v 1 = v 1 ; }

public boolean e q u a l s ( Object o ) { i f( o instanceof A) {

i f( ! v 1 . e q u a l s ( ( ( T2) o ) . v 1 ) { return f a l s e;

}

return true; }

return f a l s e; }

public S t r i n g t o S t r i n g ( ) { return ”A( ” + v 1 + ” ) ” ; }

}

T is the translation of the name t.

A is the translation of the name a.

T2 is the translation of type t2.

A record alternative of a variant definition may specify destructors for each of the components it incoorporates. The purpose of a destructor is to be able to retrieve a component of an alternative. A destructor in RSL cor-responds very much to a get method in Java, which returns the value of a field in a class. An alternative of a variant type definition may also specify reconstructors. The purpose of a reconstructor is to change a part of a record without changing the rest of the record. In Java, the idea of changing a field in a class would normally be done by a set method. However, it should be noted that a reconstructor in RSL is just a convenient way for creating a new value, in which one of the components is changed. The translation cannot be aset method in Java but must be a method creating a new object.

The translation of destructors and reconstructors in RSL into Java are as follows:

RSL:

type t1 == a(get t : t2 replace t), Java:

public abstract c l a s s T1 { // same as e a r l i e r d e f i n e d } public c l a s s A extends T1 {

private T2 v 1 ; public A(T2 v 1 ) {

t h i s. v 1 = v 1 ; }

public T2 g e t t ( ) { return v 1 ;

}

public T1 r e p l a c e t ( ) { return new A( v 1 ) ; }

/∗t o S t r i n g and e q u a l s method o m i t t e d f o l l o w s same p a t t e r n as e a r l i e r d e f i n e d .∗/

}

T1 is the translation of the name t1. A is the translation of the name a1. T2 is the translation of the type t2.

In Example 2.24, a variant definition with two alternatives a constant and a recursively defined record constructor is shown.

If the variant definition consists of only constants, it is tempting just to use an enumeration, as shown in Example 2.25. This would also be more effecient than creating an object for each value of the variant. However, in order to make the translation consistent, the same method is chosen for all kinds of variant definitions.

Example 2.26 shows a variant definitioncontaining destructors, recon-structors, and the translation of these.

The simple wildcard, which does not contain any components, is just ignored, because it is impossible to limit the number of classes extending a general super class in Java. Either a class allows for extension, which is needed because the other alternatives already extend the abstract class or a class can be declaredfinal and thereby disallow any extensions. The wildcard constructor, which contains one or more components, is also just ignored.

Variant definitions are not just used for recursive definitions. They can also be used to form a union of types which are otherwise unrelated, as shown in Example 2.27

Example 2.24 Recursive variant type definition type

Collection == empty | add(Elem, Collection), Elem

public abstract c l a s s C o l l e c t i o n { /∗e q u a l s and t o S t r i n g methods o m i t t e d∗/

}

public c l a s s empty extends C o l l e c t i o n { public boolean e q u a l s ( Object o ) {

i f( o instanceof empty ) return true;

e l s e

return f a l s e; };

public S t r i n g t o S t r i n g ( ) { return ”empty ” ;

} }

public c l a s s add extends C o l l e c t i o n { private Elem v 1 ;

private C o l l e c t i o n v 2 ;

public add ( Elem v1 , C o l l e c t i o n v 2 ) { t h i s. v 1 = v 1 ;

t h i s. v 2 = v 2 ; }

public boolean e q u a l s ( Object o ) { i f( o instanceof empty ) {

i f( ! (t h i s. v 1 . e q u a l s ( ( ( add ) o ) . v 1 ) ) ) { return f a l s e;

}

i f( ! (t h i s. v 2 . e q u a l s ( ( ( add ) o ) . v 1 ) ) ) { return f a l s e;

}

return true; }

return f a l s e; }

/∗t o S t r i n g method o m i t t e d∗/

}

/∗T r a n s l a t i o n o f Elem o m i t t e d∗/

Example 2.25Translation of variant type definition using an enumeration.

type

Color == black |white

public enum Color{black , white};

Example 2.26Variant type definition having constructors, destructors and reconstructors

type

List == empty | add(head : Elem replace head, tail : List)

public abstract c l a s s L i s t {

/∗e q u a l s and t o S t r i n g method o m i t t e d∗/

}

public c l a s s empty extends L i s t {

/∗e q u a l s and t o S t r i n g method o m i t t e d∗/

}

public c l a s s add extends L i s t { private Elem v 1 ;

private L i s t v 2 ;

public add ( Elem head , L i s t t a i l ) { v 1 = head ;

v 2 = t a i l ; }

public Elem head ( ) { return v 1 ; }

public L i s t t a i l ( ) { return v 2 ; }

public L i s t r e p l a c e h e a d ( Elem e ) { return new add ( e , v 2 ) ;

}

/∗e q u a l s and t o S t r i n g method o m i t t e d∗/

}

Example 2.27 Not recursive variant definition.

type

Figure ==

box(length : Real, width : Real) | circle(radius : Real) |

triangle(base line : Real, left angle : Real, right angle : Real)

public abstract c l a s s F i g u r e {

/∗e q u a l s and t o S t r i n g method o m i t t e d∗/

}

public c l a s s box extends F i g u r e { private double v 1 ;

private double v 2 ;

public box (double l e n g t h , double width ) { v 1 = l e n g t h ;

v 2 = width ; }

public double l e n g t h ( ) { return v1 ;

}

public double width ( ) { return v2 ;

}

/∗e q u a l s and t o S t r i n g method o m i t t e d∗/

}

public c l a s s c i r c l e extends F i g u r e { private double v 1 ;

public c i r c l e (double r a d i u s ) { v 1 = r a d i u s ;

}

public double r a d i u s ( ) { return v 1 ;

}

/∗e q u a l s and t o S t r i n g method o m i t t e d∗/

}

...

Short Record Type Definitions

Short record definitions are short hand for variant definitions with only one alternative. Thus, the translation of a short record definition is very similar to the one for a variant definition. The destructor and reconstructor of a short record definition are optional like for a variant definition. Since the short record definition has only one alternative, there is no need for an ab-stract class and a class inherited from this.

The translation from RSL into Java is as follows:

RSL:

typet :: get c1 : t1 get c2 : t2 replace c2, Java:

public c l a s s T { private T1 v 1 ; private T2 v 2 :

public T(T1 v1 , T2 v 2 ) { t h i s. v 1 = v 1 ;

t h i s. v 2 = v 2 ; }

public T1 g e t c1( ) { return v 1 ;

}

public T2 g e t c2( ) { return v 2 ;

}

public T r e p l a c e c2(T2 c 2 ) { return new T( v1 , c 2 ) ; }

}

// T r a n s l a t i o n o f t1 and t2 o m i t t e d

T is the translation of the name t.

T1 is the translation of the type t1. T2 is the translation of the type t2.

An example of translation of a short record definition is shown in Example 2.28.

Example 2.28 Translation of a short record definition.

schemeSHORT RECORD = class

type

MySRD :: sel Real : Realsel Int : Int end

public c l a s s MySRD{

private double v 1 ; private i n t v 2 ;

public MySRD(double v1 , i n t v 2 ) { t h i s. v 1 = v 1 ;

t h i s. v 2 = v 2 ; }

public double s e l R e a l ( ) { return v 1 ;

}

public i n t s e l I n t ( ) { return v 2 ;

}

/∗e q u a l s and t o S t r i n g method o m i t t e d∗/

}

Union Type Definition

Union definitions are short hand for variant definitions. They have been ex-cluded from the translation, because they allow omitting constructors of the underlying variant type. This makes it difficult to determine which alterna-tive to use at a given point, because it is not explicitly stated. The union definitions are only short hands for variant definitions, therefore the removal of union definitions does not remove any power of RSL. It does, however, make writing specifications a little more tedious.

Abbreviation Type Definition

An abbreviation definition consists of an identifier and a type expression describing the type. The identifier can be used as a reference to the type expression. The abbreviation type gives a kind of encapsulation of the details concerning the type. The idea of a class in Java is to be an encapsulation of details, this is the reason that a class in Java is chosen as translation for an abbreviation definition.

Example 2.29 Abbreviation definition type

newType = t1× t2, t1,

t2

public c l a s s newType{

public t 1 v 1 ; public t 2 v 2 ;

/∗e q u a l s and t o S t r i n g method o m i t t e d∗/

}

public c l a s s t 1 {

/∗e q u a l s and t o S t r i n g method o m i t t e d∗/

}

public c l a s s t 2 {

/∗e q u a l s and t o S t r i n g method o m i t t e d∗/

}