c. varela; adapted w/permission from s. haridi and p. van roy1 data abstraction and state abstract...

36
C. Varela; Adapted w/permission from S. Haridi and P. V an Roy 1 Data Abstraction and State Abstract Data Types (3.7) State/Data Abstraction(6.1, 6.3, 6.4.1, 6.4.2) Carlos Varela RPI Adapted with permission from: Seif Haridi KTH Peter Van Roy UCL

Post on 19-Dec-2015

213 views

Category:

Documents


0 download

TRANSCRIPT

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 1

Data Abstraction and StateAbstract Data Types (3.7)

State/Data Abstraction(6.1, 6.3, 6.4.1, 6.4.2)

Carlos Varela

RPI

Adapted with permission from:

Seif Haridi

KTH

Peter Van Roy

UCL

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 2

Abstract data types

• A datatype is a set of values and an associated set of operations

• A datatype is abstract if only it is completely described by its set of operations regradless of its implementation

• This means that it is possible to change the implementation of the datatype without changing its use

• The datatype is thus described by a set of procedures

• These operations are the only thing that a user of the abstraction can assume

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 3

Example: A Stack

• Assume we want to define a new datatype stack T whose elements are of any type T

fun {NewStack}: Stack Tfun {Push Stack T T }: Stack Tfun {Pop Stack T T }: Stack Tfun {IsEmpty Stack T }: Bool

• These operations normally satisfy certain conditions:{IsEmpty {NewStack}} = true

for any E and S0, S1={Push S0 E} and S0 ={Pop S1 E} hold

{Pop {NewStack} E} raises error

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 4

Stack (implementation)

fun {NewStack} nil end

fun {Push S E} E|S end

fun {Pop S E} case S of X|S1 then E = X S1 end end

fun {IsEmpty S} S==nil end

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 5

Stack (another implementation)

fun {NewStack} nil end

fun {Push S E} E|S end

fun {Pop S E} case S of X|S1 then E = X S1 end end

fun {IsEmpty S} S==nil end

fun {NewStack} emptyStack end

fun {Push S E} stack(E S) end

fun {Pop S E} case S of stack(X S1) then E = X S1 end end

fun {IsEmpty S} S==emptyStack end

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 6

Dictionaries

• The datatype dictionary is a finite mapping from a set T to value, where T is either atom or integer

• fun {NewDictionary}– returns an empty mapping

• fun {Put D Key Value}– returns a dictionary identical to D except Key is mapped to

Value• fun {CondGet D Key Default}

– returns the value corresponding to Key in D, otherwise returns Default

• fun {Domain D}– returns a list of the keys in D

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 7

Implementation

fun {h} nil end fun {Put Ds Key Value} case Ds of nil then [Key#Value] [] (K#V)|Dr andthen Key==K then (Key#Value) | Dr [] (K#V)|Dr andthen K>Key then (Key#Value)|(K#V)|Dr [] (K#V)|Dr andthen K<Key then (K#V)|{Put Dr Key Value} end end

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 8

Implementationfun {CondGet Ds Key Default} case Ds of nil then Default [] (K#V)|Dr andthen Key==K then V [] (K#V)|Dr andthen K>Key then Default [] (K#V)|Dr andthen K<Key then {CondGet Dr Key Default} end end fun {Domain Ds} {Map Ds fun {$ K#_} K end} end

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 9

Further implementations

• Because of abstraction, we can replace the dictionary ADT implementation using a list, whose complexity is linear (i.e., O(n)), for a binary tree implementation with logarithmic operations (i.e., O(log(n)).

• Data abstraction makes clients of the ADT unaware (other than through perceived efficiency) of the internal implementation of the data type.

• It is important that clients do not use anything about the internal representation of the data type (e.g., using {Length Dictionary} to get the size of the dictionary). Using only the interface (defined ADT operations) ensures that different implementations can be used in the future.

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 10

Secure abstract data types:Stack is not secure

fun {NewStack} nil endfun {Push S E} E|S endfun {Pop S E}

case S of X|S1 then E=X S1 endendfun {IsEmpty S} S==nil end

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 11

Secure abstract data types II

• The representation of the stack is visible:

[a b c d]

• Anyone can use an incorrect representation, i.e., by passing other language entities to the stack operation, causing it to malfunction (like a|b|X or Y=a|b|Y)

• Anyone can write new operations on stacks, thus breaking the abstraction-representation barrier

• How can we guarantee that the representation is invisible?

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 12

Secure abstract data types III

• It is not possible to build secure abstract data types in the declarative model we have seen so far (think about it!)

• The model has to be extended. Here are two ways:– By adding a new basic type, an unforgeable constant called a name– By adding encapsulated state.

• A name is like an atom except that it cannot be typed in on a keyboard or printed!– The only way to have a name is if one is given it explicitly

• There are just two operations on names:N={NewName} : returns a fresh nameN1==N2 : returns true or false

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 13

Secure abstract datatypes IV

proc {NewWrapper ?Wrap ?Unwrap} Key={NewName} in fun {Wrap X} fun {$ K} if K==Key then X end end end fun {Unwrap C} {C Key} end end

• We want to « wrap » and « unwrap » values• Let us use names to define a wrapper & unwrapper

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 14

Secure abstract data types:A secure stack

With the wrapper & unwrapper we can build a secure stack

local Wrap Unwrap in{NewWrapper Wrap Unwrap}fun {NewStack} {Wrap nil} endfun {Push S E} {Wrap E|{Unwrap S}} endfun {Pop S E}

case {Unwrap S} of X|S1 then E=X {Wrap S1} endendfun {IsEmpty S} {Unwrap S}==nil end

end

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 15

Capabilities and security• We say a computation is secure if it has well-defined and controllable

properties, independent of the existence of other (possibly malicious) entities (either computations or humans) in the system

• What properties must a language have to be secure?• One way to make a language secure is to base it on capabilities

– A capability is an unforgeable language entity (« ticket ») that gives its owner the right to perform a particular action and only that action

– In our model, all values are capabilities (records, numbers, procedures, names) since they give the right to perform operations on the values

– Having a procedure gives the right to call that procedure. Procedures are very general capabilities, since what they do depends on their argument

– Using names as procedure arguments allows very precise control of rights; for example, it allows us to build secure abstract data types

• Capabilities originated in operating systems research– A capability can give a process the right to create a file in some directory

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 16

Secure abstract datatypes V

• We add two new concepts to the computation model

• {NewChunk Record}– returns a value similar to record but its arity cannot be inspected

– recall {Arity foo(a:1 b:2)} is [a b]

• {NewName}– a function that returns a new symbolic (unforgeable, i.e. cannot be

guessed) name

– foo(a:1 b:2 {NewName}:3) makes impossible to access the third component, if you do not know the arity

• {NewChunk foo(a:1 b:2 {NewName}:3) }– Returns what ?

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 17

Secure abstract datatypes VIproc {NewWrapper ?Wrap ?Unwrap} Key={NewName} in fun {Wrap X} {NewChunk foo(Key:X)} end fun {Unwrap C} C.Key end end

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 18

Secure abstract data types:Another secure stack

With the new wrapper & unwrapper we can build another secure stack (since we only use the interface to wrap and unwrap, the code is identical to the one using higher-order programming)

local Wrap Unwrap in{NewWrapper Wrap Unwrap}fun {NewStack} {Wrap nil} endfun {Push S E} {Wrap E|{Unwrap S}} endfun {Pop S E}

case {Unwrap S} of X|S1 then E=X {Wrap S1} endendfun {IsEmpty S} {Unwrap S}==nil end

end

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 19

What is state?

• State is a sequence of values in time that contains the intermediate results of a desired computation

• Declarative programs can also have state according to this definition

• Consider the following program

fun {Sum Xs A} case Xs of X|Xr then {Sum Xr A+X} [] nil then A end end

{Browse {Sum [1 2 3 4] 0}}

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 20

What is implicit state?

The two arguments Xs and A

represent an implicit state

Xs A

[1 2 3 4] 0

[2 3 4] 1

[3 4] 3

[4] 6

nil 10

fun {Sum Xs A} case Xs of X|Xr then {Sum Xr A+X} [] nil then A end end

{Browse {Sum [1 2 3 4] 0}}

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 21

What is explicit state: Example?

XAn unboundvariable

XA cell C is created with initial value 5X is bound to C

5

XThe cell C, which X is bound to, is assigned the value 6

6

C

C

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 22

What is explicit state: Example?

XAn unboundvariable

XA cell C is created with initialvalue 5X is bound to C

5

XThe cell C, which X is bound to, is assigned the value 6

6

C

C

• The cell is a value container with a unique identity• X is really bound to the identity of the cell• When the cell is assigned, X does notchange

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 23

What is explicit state?

• X = {NewCell I}– Creates a cell with initial value I

– Binds X to the identity of the cell

• Example: X = {NewCell 0}

• {Assign X J}– Assumes X is bound to a cell C (otherwise exception)

– Changes the content of C to become J

• Y = {Access X}– Assumes X is bound to a cell C (otherwise exception)

– Binds Y to the value contained in C

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 24

Examples

• X = {NewCell 0}

• {Assign X 5}

• Y = X

• {Assign Y 10}

• {Access X} == 10 % returns true

• X == Y % returns true

X 0

X 5

Y

X 10

Y

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 25

Examples

• X = {NewCell 10}Y = {NewCell 10}

• X == Y % returns false

• Because X and Y refer to different cells, with different identities

• {Access X} == {Access Y}returns true

X 10

Y 10

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 26

Examples

• X = {NewCell 0}

• {Assign X 5}

• Y = X

• {Assign Y 10}

• X == 10 % returns false• {Access X} == 10 %

returns true

X 0

X 5

Y

X 10

Y

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 27

The model extended with cells

Semantic stack

w = f(x)z = person(a:y)y = 1u = 2x

1: w2: x........

single assignmentstore

mutable store

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 28

The stateful model

s::= skip empty statement| s1 s2 statement sequence

| ... | {NewCell x c} cell creation| {Exchange c x y} cell exchange

Exchange: bind x to the old content of c and set thecontent of the cell c to y

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 29

The stateful model

| {NewCell x c} cell creation| {Exchange c x y} cell exchange

proc {Assign C X} {Exchange C _ X} end

fun {Access C} X in{Exchange C X X}X end

Exchange: bind x to the old content of c and set thecontent of the cell c to y

C := X is syntactic sugar for {Assign C X}@C is syntactic sugar for {Access C}

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 30

Abstract data types (revisited)

• For a given functionality, there are many ways to package the ADT. We distinguish three axes.

• Open vs. secure ADT: is the internal representation visible to the program or hidden?

• Declarative vs. stateful ADT: does the ADT have encapsulated state or not?

• Bundled vs. unbundled ADT: is the data kept together from the operations or is it separable?

• Let us see what our stack ADT looks like with some of these possibilities

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 31

Stack:Open, declarative, and unbundled

• Here is the basic stack, as we saw it before:

fun {NewStack} nil endfun {Push S E} E|S endfun {Pop S E} case S of X|S1 then E=X S1 end endfun {IsEmpty S} S==nil end

• This is completely unprotected. Where is it useful? Primarily, in small programs in which expressiveness is more important than security.

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 32

Stack:Secure, declarative, and unbundled

• We can make the declarative stack secure by using a wrapper:

local Wrap Unwrapin

{NewWrapper Wrap Unwrap}fun {NewStack} {Wrap nil} endfun {Push S E} {Wrap E|{Unwrap S}} endfun {Pop S E} case {Unwrap S} of X|S1 then E=X {Wrap S1} end

endfun {IsEmpty S} {Unwrap S} ==nil end

end

• Where is this useful? In large programs where we want to protect the implementation of a declarative component.

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 33

Stack:Secure, stateful, and bundled

• This is the simplest way to make a secure stateful stack:

proc {NewStack ?Push ?Pop ?IsEmpty}C={NewCell nil}

inproc {Push X} {Assign C X|{Access C}} endfun {Pop} case {Access C} of X|S then {Assign C S} X end endfun {IsEmpty} {Access C} ==nil end

end• Compare the declarative with the stateful versions: the declarative

version needs two arguments per operation, the stateful version uses higher-order programming (instantiation)

• With some syntactic support, this is object-based programming

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 34

Stack:Secure, stateful, and unbundled

• Let us combine the wrapper with state:local Wrap Unwrapin

{NewWrapper Wrap Unwrap}fun {NewStack} {Wrap {NewCell nil}} endproc {Push W X} C={Unwrap W} in {Assign C X|{Access C}} endfun {Pop W} C={Unwrap W} in

case {Access C} of X|S then {Assign C S} X endendfun {IsEmpty S} {Access {Unwrap W}}==nil end

end• This version is stateful but lets us store the stack separate from the

operations. The same operations work on all stacks.

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 35

Four ways to package a stack

• Open, declarative, and unbundled: the usual declarative style, e.g., in Prolog and Scheme

• Secure, declarative, and unbundled: use wrappers to make the declarative style secure

• Secure, stateful, and bundled: the usual object-oriented style, e.g., in Smalltalk and Java

• Secure, stateful, and unbundled: an interesting variation on the usual object-oriented style

• Other possibilities: there are four more possibilities! Exercise: Try to write all of them.

C. Varela; Adapted w/permission from S. Haridi and P. Van Roy 36

Exercises

• Write the higher-order function Map used by the Domain function in the Dictionary ADT.

• Solve problem 17 in Section 3.10 (pg. 232). You do not need to implement it using gump, simply specify how you would add currying to Oz (syntax and semantics).

• Do exercise 2 in Section 6.10 (pg. 482).

• Read Sections 2.8.3 and 6.4.4