BeCecil

A

Core

Object-Oriented

Language

with

Block

Structure

and

Multimethods

Semantics

and

Typing

Craig

Chambers

and

Gary

T.

Leavens

TR

December

This

report

minus

the

appendices

will

appear

in

the

proceedings

of

the

The

Fourth

International

Workshop

on

Foundations

of

Object-Oriented

Languages

FOOL

Paris

France

The

full

report

also

appears

as

a

technical

report

from

the

department

of

Computer

Science

and

Engineering

University

of

Washington

Seattle

WA

numbered

CR

Categories

D.

-LSB-

Programming

Languages

-RSB-

Formal

Definitions

and

Theory

semantics

D.

-LSB-

Programming

Languages

-RSB-

Language

Classifications

object-oriented

languages

D.

-LSB-

Programming

Languages

-RSB-

Language

Constructs

and

Features

abstract

data

types

control

structures

procedures

functions

and

subroutines

D.

m

-LSB-

Programming

Languages

-RSB-

Miscellaneous

multimethods

generic

functions

type

systems

F.

-LSB-

Logics

and

Meanings

of

Programs

-RSB-

Semantics

of

Programming

Languages

operational

semantics

F.

-LSB-

Logics

and

Meanings

of

Programs

-RSB-

Studies

of

Program

Constructs

control

primitives

type

structure

Copyright

Craig

Chambers

and

Gary

T.

Leavens

Department

of

Computer

Science

Atanasoff

Hall

Iowa

State

University

Ames

Iowa

USA

BeCecil

a

Core

Object-Oriented

Language

with

Block

Structure

and

Multimethods

Semantics

and

Typing

Craig

Chambers

Department

of

Computer

Science

and

Engineering

University

of

Washington

Box

Seattle

WA

USA

-LRB-206-RRB- 685-2094

fax

-LRB-206-RRB- 543-2969

chambers@cs.washington.edu

Gary

T.

Leavens

Department

of

Computer

Science

Iowa

State

University

Atanasoff

Hall

Ames

IA

USA

-LRB-515-RRB- 294-1580

fax

-LRB-515-RRB- 294-0258

leavens@cs.iastate.edu

December

Abstract

We

present

and

analyze

the

semantics

and

static

type

system

for

BeCecil

a

theoretical

-LRB-

core

-RRB-

language

with

multimethods

BeCecil

is

a

simple

and

orthogonal

version

of

object-oriented

languages

like

Cecil

CLOS

and

Dylan

BeCecil

has

a

new

simple

mechanism

for

information

hiding

which

allows

subclassing

and

yet

can

preserve

representation

invariants

BeCecil

is

also

block-structured

within

a

block

one

can

extend

a

generic

function

with

new

multimethods

which

may

come

from

other

generic

functions

The

inheritance

relationships

of

objects

may

be

extended

in

any

block

and

are

statically

scoped

The

type

system

separates

classes

from

types

and

inheritance

from

subtyping

Subtype

relationships

are

also

extensible

and

statically

scoped

These

features

combine

to

make

BeCecil

unusually

expressive

while

still

allowing

static

typechecking

Introduction

Object-oriented

-LRB-

OO

-RRB-

languages

with

multimethods

-LSB-

Bobrow

et

al.

Moon

Chambers

-RSB-

offer

increased

expressiveness

over

languages

with

only

singly-dispatched

methods

for

the

following

reasons

dispatching

on

all

arguments

is

more

flexible

and

symmetric

than

dispatching

on

only

the

first

argument

multiple

dispatching

generalizes

and

unifies

global

procedures

singly-dispatched

methods

and

-LRB-

statically

-RRB-

overloaded

procedures

multiple

dispatching

resolves

complications

relating

to

co

versus

contravariant

redefinition

and

binary

methods

-LSB-

Bruce

et

al.

Castagna

-RSB-

Multimethods

also

lead

to

a

style

of

language

that

permits

objects

to

be

extended

at

several

points

in

a

program

By

making

such

extensions

in

a

nested

scope

one

can

customize

the

interface

of

classes

for

particular

client

applications

without

polluting

the

interface

as

seen

by

other

clients

This

style

can

also

support

more

role-based

or

subject-oriented

programming

models

-LSB-

Shilling

Sweeney

Wirfs-Brock

Johnson

Reenskaug

Anderson

Harrison

Ossher

Ossher

et

al.

Van

Hilst

Notkin

-RSB-

BeCecil

Chambers

Leavens

However

in

comparison

with

languages

with

single-dispatched

methods

languages

with

multimethods

have

received

little

theoretical

attention

Work

on

the

l

calculus

-LSB-

Ghelli

Castagna

et

al.

Castagna

et

al.

Castagna

-RSB-

and

other

languages

-LSB-

Rouaix

Agrawal

et

al.

Mugridge

et

al.

Chambers

Leavens

Chambers

Leavens

-RSB-

has

given

some

basic

ideas

for

type

systems

and

type

checking

algorithms

Although

CLOS

-LSB-

Steele

Paepcke

-RSB-

and

Dylan

-LSB-

Shalit

Feinberg

-RSB-

are

multimethod

languages

with

module

systems

their

module

systems

which

have

received

little

theoretical

attention

either

permit

encapsulation

violations

or

limit

extensibility

Thus

the

design

of

-LRB-

statically

typed

-RRB-

module

systems

that

both

allow

interesting

extensions

-LRB-

e.g.

subclasses

-RRB-

and

prevent

encapsulation

violations

and

clashes

between

independently-developed

extensions

remains

an

important

problem

-LSB-

Cook

-RSB-

We

have

been

developing

and

experimenting

with

Cecil

an

expressive

and

practical

object-oriented

language

based

on

multimethods

-LSB-

Chambers

Chambers

-RSB-

We

have

gained

practical

experience

with

programming

in

Cecil

by

writing

an

optimizing

compiler

Vortex

-LSB-

Dean

et

al.

-RSB-

We

recently

presented

a

static

type

system

efficient

typechecking

algorithm

and

module

system

for

Cecil

-LSB-

Chambers

Leavens

-RSB-

As

part

of

our

efforts

to

formalize

the

module

system

and

generalize

the

underlying

object

model

we

are

designing

a

core

language

BeCecil

that

includes

extensible

generic

functions

inheritance

and

static

type

checking

BeCecil

is

intended

to

directly

support

the

following

standard

and

novel

programming

idioms

BeCecil

supports

a

prototype-based

object

model

that

unifies

classes

and

instances

in

a

single

object

construct

supports

-LRB-

multiple

-RRB-

inheritance

between

objects

and

supports

-LRB-

mutable

-RRB-

state

and

object

identity

BeCecil

supports

multimethods

collected

in

-LRB-

first-class

-RRB-

generic

function

objects

Each

multimethod

case

of

a

generic

function

can

be

a

nested

lexically-scoped

closure

traditional

lexically-scoped

functions

are

modeled

by

generic

function

objects

with

one

case

Unlike

CLOS

or

Dylan

multimethods

are

not

artificially

linearized

in

terms

of

specificity

which

permits

ambiguous

definitions

-LRB-

that

need

to

be

prevented

by

the

type

system

-RRB-

Instance

variables

are

modeled

as

special

kinds

of

multimethod

implementations

integrating

them

into

the

regular

message

dispatching

mechanism

Special

messagesending

features

model

super-send-like

operations

to

invoke

overridden

multimethod

cases

BeCecil

supports

a

static

type

system

that

separates

types

from

objects

and

subtyping

from

code

inheritance

-LRB-

objects

conform

to

the

types

they

implement

-RRB-

and

guarantees

that

all

dynamicallydispatched

messages

will

find

a

single

most-specific

matching

multimethod

case

at

run-time

The

type

system

does

not

force

dummy

implementations

of

abstract

operations

BeCecil

supports

extensible

customizable

objects

in

that

generic

functions

superclasses

and

supertypes

can

be

added

to

existing

objects

or

types

by

external

clients

of

those

types

New

generic

functions

can

be

constructed

that

build

upon

all

the

cases

of

existing

generic

functions

in

a

sense

producing

a

customized

version

of

the

original

generic

function

-LRB-

BeCecil?s

extensibility

is

in

marked

contrast

to

the

monolithic

nature

of

traditional

class

declarations

in

existing

object-oriented

languages

and

is

motivated

in

part

by

BeCecil?s

inclusion

of

multimethods

-RRB-

BeCecil

supports

scoping

and

encapsulation

of

all

declarations

including

object

type

inheritance

subtyping

and

multimethod

declarations

limiting

their

static

visibility

and

dynamic

effect

to

a

particular

region

of

program

text

In

addition

to

traditional

uses

of

encapsulation

of

hidden

state

of

objects

this

feature

enables

clients

to

make

extensions

to

existing

objects

in

a

nested

scope

thereby

hiding

the

extensions

from

other

unrelated

clients

-LRB-

Supporting

true

scoping

of

previously-global

Block-structured

extensible

Cecil

New

types

to

which

an

existing

object

conforms

and

new

supertypes

of

an

existing

type

BeCecil

Chambers

Leavens

notions

such

as

the

inheritance

and

subtyping

graphs

and

the

set

of

multimethods

in

a

generic

function

was

a

challenge

-RRB-

BeCecil

will

support

a

notion

of

separate

typechecking

where

modules

-LRB-

named

collections

of

declarations

-RRB-

can

be

statically

typechecked

in

isolation

from

clients

unrelated

modules

and

even

any

extending

modules

-LRB-

Modular

typechecking

is

difficult

in

the

face

of

multimethods

where

ambiguities

can

arise

between

independent

additions

of

multimethod

cases

to

a

common

generic

function

-RRB-

BeCecil

strives

to

make

extension

of

existing

code

as

easy

and

useful

as

possible

without

modification

and

while

preserving

static

typechecking

This

goal

leads

to

multimethods

accessing

instance

variables

solely

through

messages

separating

types

from

classes

allowing

clients

to

extend

existing

objects

externally

-LRB-

along

with

controlling

the

scope

of

the

extensions

-RRB-

and

type

system

support

for

separate

typechecking

of

separately-developed

collections

of

declarations

BeCecil

currently

supports

all

the

desired

features

listed

above

except

named

collections

of

declarations

and

separate

typechecking

adding

modules

and

modular

typechecking

is

current

work

A

proof

that

our

type

system

is

sound

with

respect

to

the

dynamic

semantics

is

also

current

work

Although

BeCecil

is

intended

to

be

a

core

subset

of

Cecil

it

does

not

model

all

of

Cecil

directly

In

particular

it

does

not

model

non-local

returns

predicate

classes

-LSB-

Chambers

-RSB-

and

parameterized

types

The

rest

of

this

paper

is

organized

as

follows

The

dynamic

semantics

is

described

in

three

sections

Section

gives

an

overview

of

language

minus

its

typing

aspects

including

its

syntax

and

various

examples

Appendix

A

formally

defines

the

dynamic

semantics

of

the

language

and

Appendix

B

discusses

various

design

issues

related

to

the

dynamic

semantics

Similarly

BeCecil?s

type

system

is

also

described

in

three

sections

Section

gives

an

overview

of

the

type

system

Appendix

C

formally

defines

the

type

system

and

Appendix

D

discusses

various

design

issues

related

to

the

type

system

Finally

Section

discusses

related

work

in

some

detail

and

Section

offers

more

discussion

and

conclusions

The

appendix

sections

are

available

from

the

URL

ftp

-LSB-

Chambers

Leavens

-RSB-

BeCecil

Chambers

Leavens

Syntax

Overview

Sugars

and

Examples

for

the

Untyped

Subset

of

BeCecil

In

this

section

we

present

the

untyped

subset

of

BeCecil

We

first

present

the

syntax

of

this

subset

show

how

to

program

standard

OO

mechanisms

present

some

syntactic

sugars

discuss

some

small

examples

and

conclude

with

some

informal

descriptions

of

subtle

points

in

the

semantics

and

how

BeCecil

supports

abstract

data

type

-LRB-

ADT

-RRB-

patterns

We

hope

that

this

material

will

give

readers

a

feel

for

the

language

before

the

detailed

dynamic

semantics

are

presented

in

Appendix

A

-LSB-

Chambers

Leavens

-RSB-

Syntax

The

abstract

syntax

of

BeCecil

appears

in

Figure

below

except

for

the

syntax

of

the

type

system

which

is

explained

in

Section

BeCecil

is

a

call-by-value

language

-LRB-

based

on

an

indirect

-LSB-

Friedman

et

al.

-RSB-

or

P

Program

RDS

B

prelude

followed

by

a

block

RDS

Recursive-Declaration-Sequence

D

mutual

recursion

is

allowed

within

D

B

Block

RDS

E

the

recursive

declaration

sequence

provides

context

for

E

D

Declaration

object

I

object

allocates

a

new

object

named

I

inherits

inheritance

directly

inherits

from

CN

has

GF

extension

CN

to

include

the

methods

of

GF

hide

RDS

in

D

end

hide

the

declarations

of

RDS

are

only

visible

to

the

D

CN

Class-Name

I

identifier

that

names

an

object

-LRB-

a

class

-RRB-

GF

Generic-Function

attributes

I

identifier

the

methods

and

tables

of

I

method

-LRB-

F

-RRB-

-LCB-

B

-RCB-

method

like

l

a

block

abstraction

storage

-LRB-

F

-RRB-

E

storage

table

new

table

initialized

to

value

of

E

acceptor

-LRB-

F

-RRB-

I

-LCB-

B

-RCB-

acceptor

can

process

an

assignment

with

value

I

combination

favored

over

if

clash

F

Formal

argument

I

CN

the

specializer

for

this

argument

is

the

class

CN

E

Expression

I

class

name

evaluates

to

the

object

denoted

by

CN

-LRB-

AA

-RRB-

application

evaluates

operator

then

operands

left-to-right

-LRB-

AA

-RRB-

En

assignment

with

key

AA

and

value

En

sequence

evaluates

then

AA

Actual-Argument

E

undirected

applicabile

if

inherits

from

specializer

E

@CN

directed

applicable

if

also

a

CN

i

inherits

from

specializer

Figure

Abstract

syntax

of

BeCecil

-LRB-

minus

typing

aspects

-RRB-

As

usual

an

asterisk

-LRB-

-RRB-

denotes

zero

or

more

repetitions

of

the

preceding

nonterminal

In

concrete

examples

we

freely

use

parentheses

as

well

as

separators

such

as

commas

between

repeated

phrases

BeCecil

Chambers

Leavens

shared

objects

-RRB-

that

is

roughly

a

superset

of

the

l

calculus

-LSB-

Ghelli

Castagna

et

al.

Castagna

et

al.

-RSB-

Brief

Overview

As

a

start

towards

understanding

the

semantics

of

BeCecil

we

show

how

to

program

some

standard

OO

mechanisms

in

BeCecil

and

then

describe

how

to

program

some

other

basic

mechanisms

How

to

Program

Standard

OO

Mechanisms

in

BeCecil

An

object

in

BeCecil

can

be

created

only

by

an

object

declaration

Objects

in

a

program

can

act

as

classes

or

instances

in

other

OO

languages

Each

object

has

a

unique

identity

For

example

the

following

could

be

used

to

declare

a

class

-LRB-

We

use

the

suffix

rep

which

stands

for

representation

to

distinguish

classes

from

types

in

examples

-RRB-

object

An

object

may

be

declared

to

inherit

from

some

other

object

by

an

inheritance

declaration

One

can

use

more

than

one

inheritance

declaration

with

the

same

object

named

on

the

left-hand

side

to

achieve

multiple

inheritance

For

example

the

following

declares

that

inherits

from

an

object

named

any

and

declares

another

object

-LRB-

for

colored

points

-RRB-

that

inherits

from

and

an

object

named

The

object

named

any

is

used

in

our

examples

as

an

object

from

which

-LRB-

almost

-RRB-

all

objects

inherit

inherits

any

object

inherits

inherits

We

chose

to

make

BeCecil

simpler

by

not

distinguishing

the

inheritance

and

instance-of

relationships

In

this

respect

BeCecil

resembles

prototype-based

languages

-LSB-

Ungar

Smith

Chambers

Blascheck

Abadi

Cardelli

-RSB-

Since

an

instance

of

a

class

is

just

an

object

that

inherits

from

the

class

instances

of

classes

are

created

just

like

subclasses

For

example

one

could

declare

an

instance

myPoint

of

as

follows

object

myPoint

myPoint

inherits

Objects

in

BeCecil

can

also

act

as

generic

functions

A

generic

function

in

BeCecil

is

roughly

a

collection

of

multimethods

as

in

CLOS

-LSB-

Steele

Paepcke

-RSB-

Cecil

or

Dylan

-LSB-

Shalit

Feinberg

et

al.

-RSB-

-LRB-

Unlike

CLOS

or

Dylan

however

the

methods

in

a

BeCecil

generic

function

need

not

all

take

the

same

number

of

arguments

-RRB-

For

example

to

declare

the

generic

function

equal

one

would

write

the

following

In

our

examples

generic

functions

inherit

from

an

object

named

-LRB-

which

itself

inherits

from

any

-RRB-

object

equal

equal

inherits

Assuming

that

the

generic

functions

x

and

y

are

implemented

for

points

the

following

extension

-LRB-

has

-RRB-

declaration

can

be

used

to

extend

the

generic

function

equal

with

a

method

specialized

for

two

arguments

equal

has

method

-LRB-

-RRB-

-LCB-

and

-LRB-

equal

-LRB-

x

-LRB-

-RRB-

x

-LRB-

-RRB-

-RRB-

equal

-LRB-

y

-LRB-

-RRB-

y

-LRB-

-RRB-

-RRB-

-RRB-

-RCB-

An

extension

declaration

is

similar

to

a

method

declaration

in

Cecil

and

to

defmethod

in

CLOS

The

formals

have

the

form

I@CN,

where

I

is

the

name

of

the

formal

and

CN

is

the

name

of

the

formal?s

BeCecil

Chambers

Leavens

specializer

object

Note

that

there

is

a

formal

for

each

argument

unlike

single-dispatch

languages

such

as

Smalltalk

-LSB-

Goldberg

Robson

-RSB-

or

C++

-LSB-

Stroustrup

-RSB-

where

there

is

a

distinguished

receiver

-LRB-

written

self

or

this

-RRB-

that

is

not

mentioned

in

the

list

of

formals

The

body

of

the

method

is

written

between

the

curly

braces

Method

bodies

in

general

contain

a

block

which

consists

of

a

recursive

declaration

sequence

and

an

expression

which

is

evaluated

and

its

value

returned

as

the

result

of

the

method

In

the

case

of

the

above

equal

method

the

block

that

forms

the

body

has

no

declarations

but

only

an

expression

which

is

evaluated

when

the

method

is

called

and

its

value

returned

The

expression

in

the

body

of

the

above

method

calls

the

generic

function

equal

twice

but

each

time

with

integer

arguments

-LRB-

the

two

x

and

y

coordinates

of

the

points

-RRB-

thus

these

calls

to

equal

invoke

other

methods

of

the

same

generic

function

Dispatch

to

methods

is

dynamic

and

based

on

the

ancestry

of

all

the

actual

argument

objects

A

method

is

applicable

to

a

tuple

of

actuals

if

each

actual

inherits

from

the

corresponding

specializer

When

a

generic

function

is

invoked

the

generic

function

must

have

a

unique

most-specific

method

that

is

applicable

to

the

actuals

that

method

is

then

called

For

example

the

method

above

is

applicable

to

two

arguments

that

both

inherit

from

because

the

specializers

of

the

method

are

both

Instance

variables

of

an

object

are

modeled

by

storage

tables

A

storage

table

can

be

thought

of

as

a

table

or

relation

that

associates

keys

to

values

Keys

consist

of

a

tuple

of

object

identities

and

a

value

is

a

single

object

In

BeCecil

a

generic

function

can

contain

both

storage

tables

and

methods

reading

a

storage

table

looks

like

applying

a

generic

function

In

such

an

application

the

key

is

formed

from

the

identities

of

the

arguments

of

the

invocation

If

no

value

is

currently

stored

for

the

given

key

the

table?s

default

value

is

returned

For

example

consider

the

following

declarations

These

declare

two

objects

that

act

as

instance

variables

x

and

y.

Each

instance

variable

is

modeled

by

a

generic

function

with

a

storage

table

attribute

Each

storage

table

declared

can

be

thought

of

as

an

association

between

points

and

integers

-LRB-

objects

that

inherit

from

and

objects

that

inherit

from

-RRB-

The

identities

of

points

are

the

keys

to

these

tables

and

the

associated

integers

are

the

values

The

expression

following

in

each

storage

table

declaration

in

this

example

is

the

default

value

object

x

x

inherits

x

has

storage

-LRB-

-RRB-

object

y

y

inherits

y

has

storage

-LRB-

-RRB-

Since

myPoint

inherits

from

all

methods

and

storage

tables

that

have

formal

arguments

that

are

specialized

on

are

applicable

to

myPoint

For

example

the

expression

x

-LRB-

myPoint

-RRB-

returns

the

x

coordinate

for

myPoint

which

at

this

point

is

the

default

value

Storage

tables

can

be

modified

using

an

assignment

expression

in

an

assignment

the

arguments

to

the

left

of

the

form

the

key

and

the

expression

to

the

right

of

the

gives

the

value

to

be

associated

with

that

key

Thus

one

can

set

the

x

coordinate

of

myPoint

to

by

using

the

following

assignment

expression

x

-LRB-

myPoint

-RRB-

BeCecil

also

has

acceptors

which

are

like

methods

that

can

process

an

assignment

Having

acceptors

allows

any

storage

table

to

be

replaced

by

an

acceptor

and

a

method

and

also

permits

the

equivalent

of

writeonly

fields

When

used

in

an

assignment

the

key

is

bound

to

the

formals

and

the

value

to

the

right

of

the

is

bound

to

the

identifier

that

follows

the

in

the

acceptors

declaration

For

example

the

following

declares

a

generic

function

xy

with

an

acceptor

that

assigns

the

value

given

to

both

the

x

and

y

coordinates

of

the

point

that

forms

the

key

BeCecil

Chambers

Leavens

object

xy

xy

inherits

xy

has

acceptor

-LRB-

-RRB-

v

-LCB-

x

-LRB-

p

-RRB-

v

y

-LRB-

p

-RRB-

v

-RCB-

Thus

the

following

expression

would

return

xy

-LRB-

myPoint

-RRB-

plus

-LRB-

x

-LRB-

myPoint

-RRB-

y

-LRB-

myPoint

-RRB-

-RRB-

Dispatch

in

assignments

is

also

dynamic

but

only

considers

the

specializers

of

the

generic

function?s

acceptors

and

storage

tables

A

generic

function?s

methods

are

not

considered

when

dispatching

an

assignment

Similarly

when

dispatching

an

application

only

the

applicability

of

its

methods

and

storage

tables

matters

The

pattern

of

object

creation

and

initialization

can

be

easily

encapsulated

in

a

generic

function

which

allows

one

to

create

new

objects

dynamically

In

BeCecil

it

is

often

convenient

to

program

both

an

initializer

-LRB-

as

in

-LSB-

Harbison

Nelson

-RSB-

these

are

called

constructors

in

C++

-RRB-

and

a

separate

primitive

constructor

-LRB-

similar

to

a

class

method

in

Smalltalk

-RRB-

so

that

the

initializer

can

be

inherited

object

initialize

initialize

inherits

initialize

has

method

-LRB-

-RRB-

-LCB-

x

-LRB-

p

-RRB-

i

y

-LRB-

p

-RRB-

j

p

-RCB-

object

mkPoint

mkPoint

inherits

mkPoint

has

method

-LRB-

-RRB-

-LCB-

object

res

res

inherits

initialize

-LRB-

res

x

y

-RRB-

-RCB-

Note

that

because

the

declaration

of

res

in

mkPoint

is

inside

a

nested

recursive

declaration

sequence

-LRB-

the

declarations

of

the

block

that

forms

the

body

of

that

method

-RRB-

it

creates

a

new

object

each

time

that

method

is

called

Thus

block

structure

allows

one

to

create

objects

dynamically

even

though

objects

are

only

created

by

object

declarations

To

achieve

information

hiding

we

chose

to

add

just

the

capability

to

hide

a

recursive

declaration

sequence

as

this

gives

one

the

ability

to

hide

generic

functions

This

capability

is

found

in

BeCecil?s

hide

declaration

A

hide

declaration

is

similar

to

a

local

declaration

in

Standard

ML

-LSB-

Milner

et

al.

-RSB-

in

that

the

declarations

in

its

recursive

declaration

sequence

are

only

visible

in

the

declaration

sequence

that

follows

the

keyword

in

-LRB-

However

unlike

Standard

ML

the

declarations

are

all

mutually

recursive

by

default

-RRB-

As

an

example

consider

the

implementation

of

a

gray-scale

model

of

colors

in

which

the

interface

presented

to

clients

allows

them

to

create

a

color

based

on

gray

intensities

given

as

floating-point

numbers

between

and

but

for

which

the

hardware

uses

intensities

specified

by

integers

between

and

Since

the

hardware

may

change

and

since

we

wish

to

enforce

the

invariant

that

every

instance

has

all

its

intensities

given

by

integers

between

and

we

hide

the

storage

table

for

instances

of

this

class

Notice

how

the

code

given

below

resembles

say

a

C++

class

declaration

with

a

private

part

that

comes

before

the

public

part

-LRB-

Comments

start

with

two

hyphens

and

continue

to

the

end

of

that

line

as

in

Ada

-LSB-

Ada

-RSB-

and

Cecil

BeCecil

Chambers

Leavens

We

assume

that

declarations

for

generic

functions

intensity

and

paint

several

generic

functions

to

manipulate

integers

and

floating

point

numbers

and

a

class

are

given

elsewhere

-RRB-

object

inherits

hide

private

declarations

object

scale

scale

inherits

scale

has

storage

-LRB-

-RRB-

in

public

declarations

initialize

has

method

-LRB-

-RRB-

-LCB-

scale

-LRB-

c

-RRB-

truncate

-LRB-

multiply

-LRB-

min

-LRB-

max

-LRB-

intensity

-RRB-

-RRB-

-RRB-

-RRB-

c

-RCB-

intensity

has

method

-LRB-

-RRB-

-LCB-

divide

-LRB-

mkFloat

-LRB-

scale

-LRB-

c

-RRB-

-RRB-

-RRB-

-RCB-

paint

has

method

-LRB-

-RRB-

-LCB-

-RCB-

end

intensity

has

acceptor

-LRB-

-RRB-

f

-LCB-

initialize

-LRB-

c

f

-RRB-

-RCB-

It

is

worth

thinking

about

how

the

above

code

maintains

the

invariant

that

for

every

object

o

that

inherits

from

the

value

of

scale

-LRB-

o

-RRB-

is

between

and

In

stating

this

invariant

by

scale

-LRB-

o

-RRB-

we

mean

the

result

of

the

generic

function

scale

defined

in

the

hidden

declarations

-LRB-

Clients

may

define

their

own

generic

function

scale

with

a

method

specialized

on

but

because

of

static

scoping

the

generic

function

scale

referred

to

within

the

hide

declaration

is

always

the

one

defined

in

the

private

part

of

the

hide

declaration

-RRB-

The

storage

table

scale

has

a

default

value

of

which

satisfies

the

invariant

The

only

way

that

the

storage

table

can

associate

the

identity

of

o

with

some

other

value

is

by

the

use

of

the

initialize

method

because

no

other

method

in

the

hide

declaration

assigns

to

that

storage

table

no

method

within

the

hide

declaration

returns

the

scale

generic

function

and

no

code

outside

the

hide

declaration

can

access

the

scale

generic

function

Since

initialize

preserves

the

invariant

the

invariant

always

holds

Notice

that

the

argument

for

the

preservation

of

the

invariant

given

above

does

not

depend

on

o

being

created

by

a

special

generic

function

such

as

mkGrayscale

given

below

The

generic

function

mkGrayscale

is

something

that

any

client

can

write

as

it

is

written

outside

of

the

hide

declaration

object

mkGrayscale

mkGrayscale

inherits

mkGrayscale

has

method

-LRB-

-RRB-

-LCB-

object

res

res

inherits

initialize

-LRB-

res

intensity

-RRB-

-RCB-

However

a

client

can

outside

the

hide

declaration

write

a

declaration

of

a

subclass

that

does

not

have

the

implicit

behavioral

properties

of

an

instance

of

that

was

created

by

mkGrayscale

This

can

be

done

by

overriding

all

the

public

methods

and

specializing

them

on

the

new

subclass

The

prevention

of

such

imposters

is

discussed

in

Section

below

BeCecil

Chambers

Leavens

Multimethods

and

Inheritance

of

Methods

Because

BeCecil

uses

multiple-dispatch

instead

of

single-dispatch

there

is

no

trouble

in

programming

binary

methods

-LSB-

Bruce

et

al.

-RSB-

such

as

equal

as

we

have

seen

above

Moreover

the

interaction

of

multimethods

and

inheritance

is

powerful

and

avoids

the

need

to

write

an

exponential

number

of

methods

to

deal

with

all

the

cases

-LSB-

Chambers

Castagna

-RSB-

To

invoke

an

overridden

method

inherited

from

a

superclass

in

BeCecil

one

can

use

the

directed

form

of

actual

arguments

In

this

form

one

writes

an

expression

followed

by

an

at-sign

-LRB-

-RRB-

and

a

list

of

class

names

The

method

selected

must

be

such

that

both

the

object

that

is

the

value

of

the

expression

and

at

least

one

of

the

named

classes

inherit

from

the

corresponding

formal

parameter

s

specializer

For

example

the

following

is

how

one

would

write

a

class

of

gray-scale

points

as

a

subclass

of

and

Notice

how

the

equal

and

initialize

methods

use

directed

actual

arguments

to

call

the

methods

specialized

on

and

as

part

of

their

work

This

is

similar

to

the

use

of

super

in

Smalltalk

or

and

in

C++

object

grayscale

points

inherits

inherits

initalize

has

method

-LRB-

-RRB-

-LCB-

initialize

-LRB-

intensity

-RRB-

calls

initialize

for

initialize

-LRB-

i

j

-RRB-

calls

initialize

for

gsp

-RCB-

object

mkGSP

mkGSP

inherits

mkGSP

has

method

-LRB-

-RRB-

-LCB-

object

res

res

inherits

initalize

-LRB-

res

i

j

intensity

-RRB-

-RCB-

equal

has

method

-LRB-

-RRB-

-LCB-

and

-LRB-

equal

-LRB-

intensity

-LRB-

-RRB-

intensity

-LRB-

-RRB-

-RRB-

equal

-LRB-

-RRB-

-RRB-

calls

equal

for

-RCB-

Programming

Variables

Storage

tables

can

also

be

used

to

program

variables

in

BeCecil

The

only

trick

is

to

use

a

tuple

of

zero

arguments

for

the

key

The

table

then

associates

the

zero-tuple

to

some

object

which

can

be

changed

by

an

assignment

expression

For

example

the

following

block

returns

object

has

storage

-LRB-

-RRB-

-LRB-

-RRB-

plus

-LRB-

-LRB-

-RRB-

-RRB-

Programming

First-Class

Procedures

Because

generic

functions

are

objects

they

can

be

used

as

first-class

procedures

For

example

consider

the

following

generic

function

that

can

act

as

a

while-loop

This

generic

function

while

has

a

method

that

takes

two

generic

function

arguments

a

condition

-LRB-

c

-RRB-

and

a

statement

-LRB-

s

-RRB-

These

generic

functions

are

expected

to

have

zero-argument

methods

-LRB-

thunks

-RRB-

that

can

be

invoked

to

perform

parts

of

the

loop

The

implementation

of

the

method

below

relies

on

another

higher-order

generic

function

ifTrue

which

takes

BeCecil

Chambers

Leavens

a

boolean

and

a

generic

function

as

its

arguments

and

only

calls

the

generic

function

with

zero

arguments

if

the

boolean

is

true

The

generic

function

loop

passed

as

the

second

argument

to

ifTrue

is

declared

inside

the

method

for

while

The

usual

static

closures

are

made

for

methods

and

thus

c

and

s

within

loop

refer

to

the

actual

arguments

passed

to

while

object

while

while

inherits

while

has

method

-LRB-

-RRB-

-LCB-

object

loop

loop

inherits

loop

has

method

-LRB-

-RRB-

-LCB-

s

-LRB-

-RRB-

while

-LRB-

c

s

-RRB-

-RCB-

ifTrue

-LRB-

c

-LRB-

-RRB-

loop

-RRB-

-RCB-

Some

Useful

Sugars

As

can

be

seen

from

the

above

examples

BeCecil

is

a

bit

tedious

to

program

in

because

it

is

a

core

language

So

it

is

helpful

to

define

a

few

syntactic

sugars

to

make

the

programming

of

more

interesting

examples

easier

to

write

and

to

read

These

sugars

also

give

one

some

idea

of

the

expressive

power

of

BeCecil

and

can

be

used

to

compare

BeCecil

to

other

core

OO

languages

such

as

the

Abadi

and

Cardelli

calculus

-LSB-

Abadi

Cardelli

-RSB-

or

Castagna?s

-LSB-

Castagna

-RSB-

In

the

sugars

below

we

write

X

to

indicate

the

desugaring

of

a

phrase

X.

-LRB-

It

should

be

understood

that

if

X

is

a

BeCecil

phrase

then

X

is

just

X

with

its

subphrases

recursively

desugared

-RRB-

We

first

discuss

declaration

sugars

then

formal

argument

and

expression

sugars

Declaration

Sugars

The

declaration

sugars

in

this

section

generally

produce

a

sequence

of

declarations

which

are

to

be

inserted

at

the

point

where

the

sugar

occurs

That

is

the

desugaring

does

not

produce

a

nested

declaration

sequence

but

simply

several

declarations

at

the

same

level

as

the

sugar

appears

For

example

consider

the

following

sugared

declarations

object

inherits

y

z

any

object

q

The

middle

declaration

above

is

a

sugared

declaration

form

The

desugaring

rule

for

it

is

the

following

inherits

CNn

inherits

inherits

CNn

Therefore

the

desugaring

of

the

above

example

produces

the

following

sequence

of

declarations

object

inherits

y

inherits

z

inherits

any

object

q

Like

the

first

desugaring

rule

given

above

the

following

declaration

sugar

also

allows

one

to

more

succinctly

declare

direct

inheritance

relationships

object

I

inherits

CNn

object

I

I

inherits

CNn

BeCecil

Chambers

Leavens

In

practical

examples

it

is

convenient

to

have

ways

to

declare

objects

that

are

to

be

used

as

generic

functions

Hence

the

following

sugars

gf

I

object

I

inherits

The

following

sugar

allows

one

to

declare

a

function

with

a

single

method

more

easily

fun

I

-LRB-

F

-RRB-

-LCB-

B

-RCB-

gf

I

I

has

method

-LRB-

F

-RRB-

-LCB-

B

-RCB-

The

following

sugars

allows

one

to

conveniently

declare

objects

that

are

to

be

used

as

variables

and

as

fields

-LRB-

instance

variables

-RRB-

A

variable

is

modeled

by

a

generic

function

with

a

zero-argument

storage

table

A

field

is

modeled

by

a

generic

function

with

a

one-argument

storage

table

The

argument

of

such

a

storage

table

is

the

record

and

the

value

of

that

record?s

field

is

returned

or

updated

by

invoking

or

assigning

to

the

storage

table

var

I

E

gf

I

I

has

storage

-LRB-

-RRB-

E

field

I

of

CN

E

gf

I

I

has

storage

-LRB-

x@CN

-RRB-

E

where

x

is

a

fresh

identifier

Formal

Argument

Sugar

If

the

object

any

is

used

as

a

class

from

which

-LRB-

almost

-RRB-

all

others

inherit

as

in

Cecil

and

our

examples

then

a

formal

parameter

specialized

on

any

is

effectively

not

specialized

at

all

Thus

the

following

sugar

for

formal

arguments

allows

one

to

omit

the

specializer

if

it

is

any

I

I

any

Expression

Sugars

For

real

programming

it

is

quite

convenient

to

be

able

to

use

blocks

as

expressions

Such

a

sugar

makes

it

easy

to

have

further

sugars

that

made

anonymous

concrete

objects

with

a

given

generic

function

value

-LRB-

like

lambda

in

Scheme

-LSB-

Clinger

Rees

-RSB-

-RRB-

various

flavors

of

let-expressions

and

even

Smalltalk-like

thunks

as

we

shall

see

However

unlike

the

sugars

described

above

the

sugar

for

block

expressions

of

the

form

-LCB-

B

-RCB-

is

not

a

local

expression

sugar

as

it

involves

adding

new

declarations

to

the

block

or

declaration

list

in

which

the

block

expression

appears

Because

such

a

sugar

is

somewhat

complex

to

explain

we

do

not

describe

it

formally

but

instead

give

an

example

to

clarify

how

this

could

be

done

Consider

the

following

some

declarations

plus

-LRB-

-LCB-

var

x

times

-LRB-

x

-LRB-

-RRB-

x

-LRB-

-RRB-

-RRB-

-RCB-

-LCB-

var

y

fun

f

-LRB-

-RRB-

-LCB-

y

-LRB-

-RRB-

plus

-LRB-

y

-LRB-

-RRB-

-RRB-

y

-LRB-

-RRB-

-RCB-

f

-LRB-

y

-LRB-

-RRB-

-RRB-

-RCB-

-RRB-

BeCecil

Chambers

Leavens

This

would

desugar

as

follows

by

adding

a

new

method

-LRB-

named

by

a

fresh

identifier

-RRB-

for

each

nested

block

and

a

call

to

that

method

in

the

place

where

the

nested

block

occurred

in

the

original

expression

some

declarations

fun

-LRB-

-RRB-

-LCB-

var

x

times

-LRB-

x

-LRB-

-RRB-

x

-LRB-

-RRB-

-RRB-

-RCB-

fun

-LRB-

-RRB-

-LCB-

var

y

fun

f

-LRB-

-RRB-

-LCB-

y

-LRB-

-RRB-

plus

-LRB-

y

-LRB-

-RRB-

-RRB-

y

-LRB-

-RRB-

-RCB-

f

-LRB-

y

-LRB-

-RRB-

-RRB-

-RCB-

plus

-LRB-

-LRB-

-RRB-

-LRB-

-RRB-

-RRB-

By

iterating

this

process

one

can

eliminate

all

such

block

expressions

and

still

preserve

scoping

Using

this

it

is

even

possible

to

regard

sequence

expressions

as

a

syntactic

sugar

-LSB-

Abadi

Cardelli

-RSB-

However

because

these

are

not

local

sugars

-LRB-

they

do

not

operate

on

expressions

in

place

-RRB-

we

have

chosen

to

include

sequence

expressions

directly

in

the

syntax

of

BeCecil

In

some

sense

it

would

be

simpler

to

add

block

expressions

as

a

primitive

to

BeCecil

enabling

all

of

these

other

sugars

but

that

complicates

the

proof

of

type

soundness

by

making

the

syntax

of

expressions

and

blocks

-LRB-

and

hence

declarations

-RRB-

mutually

recursive

The

present

desugared

syntax

does

not

allow

blocks

within

expressions

and

thus

somewhat

simplifies

the

proof

In

what

follows

we

regard

block

expressions

of

the

form

-LCB-

B

-RCB-

as

syntactic

sugars

Assuming

the

sugar

for

blocks

the

first

local

expression

sugar

is

the

following

which

creates

an

instance

of

a

class

named

CN

new

CN

-LCB-

object

I

inherits

CN

I

-RCB-

where

I

is

a

fresh

identifier

-LRB-

not

free

in

CN

-RRB-

One

can

use

the

following

expression

sugar

to

make

anonymous

concrete

objects

with

a

given

generic

function

attribute

-LRB-

like

lambda

in

Scheme

-RRB-

anon

GF

-LCB-

object

I

inherits

I

has

GF

I

-RCB-

where

I

is

a

fresh

identifier

With

anonymous

generic

functions

one

can

desugar

simultaneous

and

sequential

eagerly-evaluated

letexpressions

-LRB-

These

work

for

all

objects

that

inherit

from

any

-RRB-

let

In

En

in

-LRB-

anon

method

-LRB-

In

-RRB-

-LCB-

-RCB-

-RRB-

-LRB-

En

-RRB-

let

In

En

in

let

in

let

In

En

in

For

writing

control

structures

it

is

helpful

to

have

a

sugar

for

making

parameterless

procedures

-LRB-

thunks

-RRB-

We

adapt

part

of

the

syntax

for

Smalltalk

blocks

for

this

-LSB-

B

-RSB-

anon

method

-LRB-

-RRB-

-LCB-

B

-RCB-

BeCecil

Chambers

Leavens

Some

Small

Examples

In

this

section

we

show

some

small

examples

of

datatypes

programmed

in

BeCecil

The

Untyped

Standard

Prelude

To

make

the

examples

more

interesting

the

following

are

assumed

as

the

prelude

for

example

programs

throughout

this

section

and

throughout

Appendix

A

and

Appendix

B

The

declarations

in

this

untyped

standard

prelude

include

that

of

an

object

nothing

which

can

also

act

as

a

generic

function

with

no

arguments

This

object

is

used

as

the

return

value

for

procedures

that

do

not

wish

to

return

anything

We

use

the

trick

of

making

this

a

generic

function

so

that

it

can

be

passed

to

higher-order

functions

such

as

if

The

standard

prelude

also

declares

some

objects

to

be

used

as

ancestors

and

integer

and

floating

point

literals

such

as

and

In

various

examples

we

will

also

assume

some

generic

functions

with

methods

that

operate

on

numbers

such

as

plus

less

leq

etc.

the

untyped

standard

prelude

object

nothing

used

for

methods

that

do

not

want

to

return

anything

nothing

has

method

-LRB-

-RRB-

-LCB-

nothing

-RCB-

object

any

inherits

nothing

superclass

of

all

other

classes

object

inherits

any

object

inherits

any

object

inherits

object

inherits

object

inherits

numeric

literals

are

considered

to

be

identifiers

object

inherits

object

inherits

object

inherits

Boolean

The

Booleans

can

be

coded

much

as

in

Smalltalk

-LSB-

Goldberg

Robson

-RSB-

In

coding

this

example

we

adopt

the

position

of

only

hiding

storage

tables

for

objects

Thus

one

can

not

guarantee

that

there

are

only

two

Boolean

objects

in

a

program

but

allowing

all

classes

to

be

subclassed

is

standard

for

OO

languages

for

example

in

Smalltalk

one

can

make

new

subclasses

of

Boolean

-LRB-

On

the

other

hand

Java

-LSB-

Gosling

et

al.

-RSB-

and

Dylan

have

mechanisms

that

can

prevent

subclassing

-RRB-

This

point

of

view

has

the

advantage

of

allowing

clients

to

specialize

on

true

and

false

Having

true

and

false

also

be

thunks

that

return

themselves

is

useful

when

one

does

not

need

short-circuit

evaluation

see

the

equal

method

for

in

Section

object

inherits

any

gf

if

implemented

by

subclasses

gf

not

also

implemented

by

subclasses

gf

equal

implemented

below

fun

ifTrue

-LRB-

-RRB-

-LCB-

if

-LRB-

b

c

nothing

-RRB-

-RCB-

fun

and

-LRB-

-RRB-

-LCB-

if

-LRB-

b

c

false

-RRB-

-RCB-

fun

or

-LRB-

-RRB-

-LCB-

if

-LRB-

b

true

c

-RRB-

-RCB-

object

true

inherits

true

has

method

-LRB-

-RRB-

-LCB-

true

-RCB-

useful

when

a

thunk

that

returns

true

is

desired

if

has

method

-LRB-

b@true,

-RRB-

-LCB-

c

-LRB-

-RRB-

-RCB-

not

has

method

-LRB-

b@true

-RRB-

-LCB-

false

-RCB-

object

false

inherits

BeCecil

Chambers

Leavens

false

has

method

-LRB-

-RRB-

-LCB-

false

-RCB-

useful

when

a

thunk

that

returns

false

is

desired

if

has

method

-LRB-

b@false,

-RRB-

-LCB-

a

-LRB-

-RRB-

-RCB-

not

has

method

-LRB-

b@false

-RRB-

-LCB-

true

-RCB-

equal

has

method

-LRB-

-RRB-

-LCB-

false

-RCB-

equal

has

method

-LRB-

x@true,

y@true

-RRB-

-LCB-

true

-RCB-

equal

has

method

-LRB-

x@false,

y@false

-RRB-

-LCB-

true

-RCB-

collection

The

following

is

an

abstract

class

for

collections

It

gives

an

implementation

of

length

that

can

be

inherited

by

concrete

objects

that

implement

do

object

inherits

any

gf

isEmpty

to

be

implemented

by

subclasses

gf

do

to

be

implemented

by

subclasses

fun

length

-LRB-

-RRB-

-LCB-

var

res

do

-LRB-

c

anon

method

-LRB-

x

-RRB-

-LCB-

res

-LRB-

-RRB-

plus

-LRB-

res

-LRB-

-RRB-

-RRB-

nothing

-RCB-

-RRB-

res

-LRB-

-RRB-

-RCB-

list

The

following

and

the

next

several

examples

below

give

an

implementation

of

lists

a

la

Cook

-LSB-

Cook

-RSB-

That

is

we

use

two

abstract

classes

and

a

concrete

object

and

a

concrete

class

The

abstract

class

defines

the

protocol

for

accessing

the

elements

of

a

list

and

gives

a

general

implementation

of

do

that

can

be

inherited

by

concrete

objects

object

inherits

gf

head

to

be

implemented

by

subclasses

gf

tail

to

be

implemented

by

subclasses

do

has

method

-LRB-

-RRB-

-LCB-

if

-LRB-

isEmpty

-LRB-

c

-RRB-

nothing

-LSB-

b

-LRB-

head

-LRB-

c

-RRB-

-RRB-

do

-LRB-

tail

-LRB-

c

-RRB-

b

-RRB-

-RSB-

-RRB-

-RCB-

Since

BeCecil

does

not

distinguish

between

classes

and

objects

the

empty

list

can

be

implemented

directly

as

a

concrete

object

that

inherits

from

object

inherits

isEmpty

has

method

-LRB-

n@nil

-RRB-

-LCB-

true

-RCB-

tail

has

method

-LRB-

n@nil

-RRB-

-LCB-

-RCB-

or

one

could

use

the

trick

below

head

has

method

-LRB-

n@nil

-RRB-

-LCB-

head

-LRB-

n

-RRB-

-RCB-

loop

forever

nonempty

lists

and

cons

The

following

gives

the

code

for

and

We

use

two

classes

so

that

one

can

inherit

the

isEmpty

method

from

more

easily

-LRB-

in

other

nonempty

list

representations

that

do

not

want

to

inherit

from

-RRB-

The

fields

of

are

hidden

The

hiding

of

the

fields

makes

like

a

class

with

private

instance

variables

with

private

meaning

the

same

as

in

C++

-LRB-

It

is

unclear

how

to

support

something

like

the

protected

notion

of

C++

-RRB-

The

object

is

used

for

the

default

value

of

list

elements

We

use

an

initialization

method

to

allow

subclasses

of

to

initialize

the

hidden

fields

object

inherits

isEmpty

has

method

-LRB-

-RRB-

-LCB-

false

-RCB-

BeCecil

Chambers

Leavens

object

inherits

any

object

inherits

gf

initialize

generic

initialization

function

hide

field

hd

of

field

tl

of

in

initialize

has

method

-LRB-

x

-RRB-

-LCB-

hd

-LRB-

c

-RRB-

x

tl

-LRB-

c

-RRB-

l

c

-RCB-

tail

has

method

-LRB-

-RRB-

-LCB-

tl

-LRB-

l

-RRB-

-RCB-

head

has

method

-LRB-

-RRB-

-LCB-

hd

-LRB-

l

-RRB-

-RCB-

tail

has

acceptor

-LRB-

-RRB-

-LCB-

tl

-LRB-

l

-RRB-

-RCB-

head

has

acceptor

-LRB-

-RRB-

-LCB-

hd

-LRB-

l

-RRB-

-RCB-

end

fun

cons

-LRB-

x

-RRB-

-LCB-

initialize

-LRB-

new

x

l

-RRB-

-RCB-

The

implementation

of

the

equal

generic

function

for

lists

is

broken

into

three

cases

using

multimethod

dispatch

equal

has

method

-LRB-

-RRB-

-LCB-

false

-RCB-

equal

has

method

-LRB-

x@nil,

y@nil

-RRB-

-LCB-

true

-RCB-

equal

has

method

-LRB-

-RRB-

-LCB-

and

-LRB-

equal

-LRB-

hd

-LRB-

x

-RRB-

hd

-LRB-

y

-RRB-

-RRB-

-LSB-

equal

-LRB-

tl

-LRB-

x

-RRB-

tl

-LRB-

y

-RRB-

-RRB-

-RSB-

-RRB-

-RCB-

interval

The

ability

to

add

new

implementations

of

a

type

without

changing

existing

code

is

a

hallmark

of

OO

programming

Cook

considered

another

example

to

show

this

namely

adding

intervals

of

integers

as

another

subclass

of

Notice

how

in

our

example

below

the

equal

method

is

specialized

to

take

advantage

of

knowledge

of

the

representations

when

both

lists

are

intervals

which

results

in

a

faster

method

than

the

default

for

nonempty

lists

given

above

Another

thing

to

notice

about

this

example

is

the

programming

of

the

assign

and

clone

methods

these

are

used

in

the

next

example

below

Finally

notice

that

the

coding

of

initialize

maintains

the

invariant

for

all

objects

o

that

inherit

from

lower

-LRB-

o

-RRB-

upper

-LRB-

o

-RRB-

object

inherits

hide

field

lower

of

field

upper

of

in

initialize

has

method

-LRB-

-RRB-

-LCB-

lower

-LRB-

i

-RRB-

min

-LRB-

lb

ub

-RRB-

upper

-LRB-

i

-RRB-

max

-LRB-

lb

ub

-RRB-

i

-RCB-

gf

assign

like

C++

assignment

operator

assign

has

method

-LRB-

-RRB-

-LCB-

lower

-LRB-

l

-RRB-

lower

-LRB-

r

-RRB-

upper

-LRB-

l

-RRB-

upper

-LRB-

r

-RRB-

l

-RCB-

tail

has

method

-LRB-

-RRB-

-LCB-

BeCecil

Chambers

Leavens

let

plus

-LRB-

lower

-LRB-

l

-RRB-

-RRB-

in

if

-LRB-

greater

-LRB-

upper

-LRB-

l

-RRB-

-RRB-

-LSB-

-RSB-

-LSB-

var

res

clone

-LRB-

l

-RRB-

lower

-LRB-

res

-LRB-

-RRB-

-RRB-

res

-LRB-

-RRB-

-RSB-

-RRB-

-RCB-

head

has

method

-LRB-

-RRB-

-LCB-

lower

-LRB-

l

-RRB-

-RCB-

equal

has

method

-LRB-

-RRB-

-LCB-

and

-LRB-

equal

-LRB-

lower

-LRB-

x

-RRB-

lower

-LRB-

y

-RRB-

-RRB-

equal

-LRB-

upper

-LRB-

x

-RRB-

upper

-LRB-

y

-RRB-

-RRB-

-RRB-

-RCB-

end

fun

mkInterval

-LRB-

-RRB-

-LCB-

initialize

-LRB-

new

lb

ub

-RRB-

-RCB-

gf

clone

clone

has

method

-LRB-

-RRB-

-LCB-

assign

-LRB-

new

r

-RRB-

-RCB-

The

following

example

which

builds

on

the

interval

and

examples

above

shows

how

to

use

directed

actuals

to

inherit

methods

Directed

actuals

are

used

all

the

methods

except

mkGrayInterval

and

clone

The

directed

actuals

prevent

recursion

much

as

super

would

in

Smalltalk

or

equal

would

in

C++

By

overriding

assign

and

clone

the

tail

method

is

inherited

without

further

rewriting

object

inherits

initialize

has

method

-LRB-

-RRB-

-LCB-

initialize

-LRB-

intensity

-RRB-

initialize

-LRB-

lb

ub

-RRB-

-RCB-

assign

has

method

-LRB-

-RRB-

-LCB-

initialize

-LRB-

intensity

-LRB-

r

-RRB-

-RRB-

assign

-LRB-

-RRB-

-RCB-

fun

mkGrayInterval

-LRB-

-RRB-

-LCB-

initialize

-LRB-

new

lb

ub

intensity

-RRB-

-RCB-

clone

has

method

-LRB-

-RRB-

-LCB-

assign

-LRB-

new

gi

-RRB-

-RCB-

equal

has

method

-LRB-

-RRB-

-LCB-

and

-LRB-

equal

-LRB-

intensity

-LRB-

x

-RRB-

intensity

-LRB-

y

-RRB-

-RRB-

equal

-LRB-

-RRB-

-RRB-

-RCB-

The

following

example

shows

how

a

storage

table

with

two

arguments

can

be

used

as

a

one-dimensional

array

The

class

implements

one-dimensional

arrays

of

floats

The

function

while

used

in

this

example

was

described

in

Section

Notice

that

the

use

of

both

an

acceptor

and

a

method

for

the

generic

function

sub

allows

one

to

use

a

pleasing

notation

for

array

subscripting

while

still

allowing

bounds

checking

For

example

one

can

write

sub

-LRB-

myArray

-RRB-

object

inherits

BeCecil

Chambers

Leavens

hide

object

inherits

any

has

storage

-LRB-

-RRB-

field

of

in

initialize

has

method

-LRB-

-RRB-

-LCB-

-LRB-

a

-RRB-

n

do

-LRB-

a

anon

method

-LRB-

i

-RRB-

-LCB-

-LRB-

a

i

-RRB-

-RCB-

-RRB-

a

-RCB-

isEmpty

has

method

-LRB-

-RRB-

-LCB-

less

-LRB-

-LRB-

a

-RRB-

-RRB-

-RCB-

do

has

method

-LRB-

-RRB-

-LCB-

foreach

-LRB-

a

anon

method

-LRB-

i

-RRB-

-LCB-

b

-LRB-

-LRB-

a

i

-RRB-

-RRB-

-RCB-

-RRB-

-RCB-

fun

foreach

-LRB-

-RRB-

-LCB-

var

i

while

-LRB-

-LSB-

leq

-LRB-

i

-RRB-

-RSB-

-LSB-

b

-LRB-

i

-RRB-

i

-LRB-

-RRB-

plus

-LRB-

i

-LRB-

-RRB-

-RRB-

-RSB-

-RRB-

-RCB-

gf

sub

short

for

subscript

sub

has

method

-LRB-

-RRB-

-LCB-

ifTrue

-LRB-

and

-LRB-

leq

-LRB-

i

-RRB-

-LSB-

leq

-LRB-

i

-LRB-

a

-RRB-

-RRB-

-RSB-

-RRB-

-LSB-

-LRB-

a

i

-RRB-

-RSB-

-RRB-

-RCB-

sub

has

acceptor

-LRB-

-RRB-

e

-LCB-

ifTrue

-LRB-

and

-LRB-

leq

-LRB-

i

-RRB-

-LSB-

leq

-LRB-

i

-LRB-

a

-RRB-

-RRB-

-RSB-

-RRB-

-LSB-

-LRB-

a

i

-RRB-

e

a

-RSB-

-RRB-

-RCB-

end

fun

mkArray

-LRB-

-RRB-

-LCB-

initialize

-LRB-

new

n

-RRB-

-RCB-

Block

Structure

Extensions

and

Customization

in

Nested

Scopes

BeCecil

is

designed

to

enable

objects

to

be

extensible

In

this

section

we

discuss

how

methods

and

inheritance

relationships

can

be

extended

and

how

these

extensions

are

effected

by

nested

scoping

We

also

describe

how

in

a

nested

recursive

declaration

sequence

one

can

customize

that

recursive

declaration

sequence?s

view

of

generic

functions

The

concept

of

scope

is

a

bit

tricky

with

hide

declarations

in

BeCecil

hence

we

avoid

that

term

except

when

making

general

statements

about

nested

scopes

There

are

two

more

precise

concepts

that

we

use

instead

The

first

is

the

usual

notion

of

the

visibility

of

a

declaration

this

is

the

area

of

the

program

text

in

which

the

declaration

has

effect

We

also

speak

of

area

of

visibility

of

a

name

meaning

the

area

in

which

the

declaration

that

introduced

the

name

is

visible

The

second

is

the

concept

of

an

contour

of

an

object

declaration

this

is

the

area

of

the

program

text

in

which

one

may

use

extension

-LRB-

has

-RRB-

declarations

that

add

methods

or

storage

tables

to

the

object?s

generic

function

value

We

abuse

terminology

and

refer

to

the

contour

of

a

name

meaning

the

contour

of

the

name?s

object

declaration

Contours

correspond

to

recursive

declaration

sequences

in

the

syntax

because

only

within

the

recursive

declaration

sequence

where

an

object

is

declared

can

it

be

extended

The

reason

that

an

object

can

only

be

extended

within

the

recursive

declaration

sequence

in

which

it

is

declared

is

that

otherwise

an

object

might

be

extended

in

two

different

ways

in

different

nested

contours

Since

the

hidden

declarations

of

a

hide

declaration

form

a

recursive

declaration

sequence

this

means

that

privacy

is

based

on

generic

functions

not

individual

methods

in

BeCecil

That

is

one

can

not

extend

the

BeCecil

Chambers

Leavens

same

generic

function

in

both

parts

of

a

hide

declaration

In

this

respect

BeCecil

follows

CLOS

and

Dylan

which

also

base

privacy

on

generic

functions

As

an

example

and

further

explanation

of

these

concepts

consider

Figure

In

this

figure

there

are

two

hide

declarations

within

an

outer

recursive

declaration

sequence

The

visibility

of

hidden

declarations

in

a

hide

is

not

surprising

For

example

is

visible

within

the

entire

hide

declaration

in

which

it

is

declared

including

the

public

-LRB-

non-hidden

-RRB-

part

The

public

declarations

of

a

hide

declaration

are

visible

within

all

of

the

surrounding

recursive

declaration

sequence

Thus

a

declaration

need

only

be

put

in

the

public

part

of

a

hide

declaration

if

it

needs

to

see

the

hidden

declarations

To

simplify

things

a

bit

neither

set

of

declarations

in

a

hide

declaration

may

shadow

the

other

Since

recursive

declaration

sequences

allow

mutual

recursion

is

visible

within

the

outermost

recursive

declaration

sequence

for

example

it

is

visible

where

the

declaration

of

object

x

resides

Since

in

this

example

no

names

are

redeclared

there

are

no

holes

in

the

visibility

of

any

of

the

declarations

in

Figure

In

Figure

one

can

extend

only

within

the

recursive

declaration

sequence

in

which

it

is

declared

The

contour

of

this

recursive

declaration

sequence

is

the

small

box

-LRB-

-RRB-

that

surrounds

its

declaration

Although

is

visible

in

the

public

part

of

that

hide

declaration

it

can

not

be

extended

there

because

that

is

not

part

of

the

same

recursive

declaration

sequence

The

block

that

forms

the

body

of

the

method

for

x

at

the

bottom

of

the

outermost

hide

declaration

in

the

figure

-LRB-

-RRB-

also

is

not

part

of

the

recursive

declaration

sequence

in

which

x

is

declared

and

thus

x

can

not

be

extended

there

However

BeCecil

does

provide

mechanisms

based

on

the

l

calculus

for

customizing

generic

functions

within

a

nested

contour

The

identifier

and

combination

generic

function

attributes

allow

one

to

use

the

generic

function

value

of

another

object

-LRB-

perhaps

declared

in

a

surrounding

contour

-RRB-

when

customizing

a

nested

contour?s

view

of

a

generic

function

For

example

suppose

one

wants

to

debug

the

equal

method

by

calling

it

with

several

different

inputs

and

that

one

wants

to

print

a

message

before

and

after

it

is

called

with

arguments

that

inherit

from

Then

one

could

write

the

following

which

defines

a

Figure

Illustration

of

the

contours

and

areas

of

visibility

of

some

declarations

area

of

visibility

of

area

of

visibility

of

area

of

visibility

of

x

y

contour

of

contour

of

contour

of

x

y

object

x

hide

object

inherits

x

inherits

y

hide

object

inherits

in

object

inherits

end

object

inherits

in

object

inherits

inherits

inherits

y

x

has

method

-LRB-

-RRB-

-LCB-

-RCB-

end

object

y

BeCecil

Chambers

Leavens

generic

function

which

has

all

the

methods

of

equal

except

that

the

method

specialized

on

two

arguments

is

replaced

by

the

debugging

version

-LRB-

Note

that

recursive

calls

from

within

the

methods

of

equal

are

not

sent

to

and

would

not

be

even

if

the

name

were

equal

because

with

static

scoping

the

name

equal

in

such

methods

refers

to

the

generic

function

defined

in

the

outer

contour

-RRB-

fun

-LRB-

-RRB-

-LCB-

gf

has

equal

method

-LRB-

-RRB-

-LCB-

print

-LRB-

calling

equal

with

args

-RRB-

var

res

equal

-LRB-

-RRB-

print

-LRB-

the

call

returned

res

-LRB-

-RRB-

-RRB-

res

-LRB-

-RRB-

-RCB-

-LRB-

-RRB-

-RCB-

The

block

structure

of

BeCecil

also

effects

inheritance

As

as

start

towards

explaining

this

interaction

it

is

important

to

first

look

at

the

effect

of

an

inheritance

declaration

disregarding

block

structure

for

the

moment

The

only

dynamic

effect

of

an

inheritance

declaration

is

on

the

applicability

and

relative

specificity

of

methods

storage

tables

and

acceptors

for

objects

that

can

see

it

To

ease

this

kind

of

discussion

let

us

call

something

that

is

either

a

method

storage

table

or

acceptor

a

case

Specificity

of

cases

is

based

on

the

pointwise

extension

of

an

inheritance

relation

to

the

specializers

of

cases

That

is

a

case

is

as

specific

as

if

they

have

the

same

number

of

formals

and

if

the

specializers

of

each

inherit

-LRB-

directly

or

indirectly

-RRB-

from

the

corresponding

specializer

of

We

say

that

overrides

or

is

more

specific

than

if

is

as

specific

as

but

their

specializers

are

different

Let

us

also

call

a

case

that

is

either

a

method

or

a

storage

table

an

invocable

Recall

that

among

a

generic

function?s

invocables

the

most

specific

one

that

is

applicable

to

the

actual

arguments

is

used

For

example

in

the

following

block

the

last

method

is

called

because

it

is

more

specific

than

the

others

equal

has

method

-LRB-

-RRB-

-LCB-

-RCB-

equal

has

method

-LRB-

-RRB-

-LCB-

-RCB-

equal

has

method

-LRB-

-RRB-

-LCB-

-RCB-

this

one

is

called

equal

-LRB-

-RRB-

A

generic

function

must

use

some

inheritance

relation

to

decide

the

applicability

and

specificity

of

its

cases

What

inheritance

relation

should

it

use

If

a

programming

language

only

allows

inheritance

relations

to

be

defined

at

the

top-level

then

there

is

no

problem

but

in

BeCecil

objects

and

their

inheritance

relations

may

be

defined

in

several

places

We

investigated

several

alternatives

-LRB-

see

Section

B.

for

a

discussion

of

them

-RRB-

but

to

reason

statically

about

a

program

and

in

particular

to

permit

static

type

checking

the

inheritance

relation

used

can

not

vary

dynamically

Thus

the

inheritance

relation

used

is

the

one

that

is

defined

in

the

recursive

declaration

sequence

-LRB-

and

surrounding

contours

-RRB-

where

the

generic

function

is

defined

For

this

reason

each

object

contains

the

this

inheritance

relation

The

inheritance

relation

recorded

within

an

object

also

serves

another

purpose

in

that

it

defines

the

object?s

ancestry

The

problem

solved

by

this

is

that

dynamically

created

objects

do

not

appear

in

the

inheritance

relations

of

generic

functions

that

are

not

declared

in

recursive

declaration

sequences

where

the

object?s

declaration

is

visible

For

example

consider

the

following

code

The

inheritance

relation

that

is

recorded

in

the

object

push

says

that

inherits

from

any

but

says

nothing

about

objects

created

within

the

body

of

f.

Of

course

it

can

not

since

the

body

of

f

is

a

nested

contour

But

then

how

is

the

call

to

push

in

the

body

of

f

supposed

to

work

It

would

seem

that

the

newly

created

object

does

not

according

to

the

inheritance

relation

recorded

for

push

inherit

from

This

is

true

but

the

object

myStack

BeCecil

Chambers

Leavens

does

know

that

it

inherits

from

-LRB-

and

from

any

-RRB-

So

the

application

works

if

some

ancestor

of

myStack

is

known

to

be

object

inherits

any

gf

push

push

has

method

-LRB-

-RRB-

-LCB-

-RCB-

fun

f

-LRB-

-RRB-

-LCB-

object

myStack

inherits

push

-LRB-

myStack

-RRB-

-RCB-

f

-LRB-

-RRB-

Now

consider

a

variation

on

the

above

example

where

the

generic

function

and

one

of

the

arguments

come

from

different

contours

In

the

following

the

inheritance

relationship

between

and

is

only

known

within

the

function

nested

Inside

nested

the

generic

function

size

is

declared

and

assigned

to

the

variable

g

The

generic

function

size

has

an

inheritance

relation

that

knows

that

inherits

from

The

variable

x

is

assigned

an

object

that

inherits

from

but

which

does

not

have

as

an

ancestor

The

application

at

the

end

works

however

because

the

object

stored

in

x

has

an

ancestor

that

is

known

to

inherit

from

the

specializer

of

the

generic

function

stored

in

g

-LRB-

according

to

its

inheritance

relation

-RRB-

object

inherits

any

object

inherits

any

var

g

anon

method

-LRB-

-RRB-

-LCB-

-RCB-

var

x

new

fun

nested

-LRB-

-RRB-

-LCB-

inherits

gf

size

size

has

method

-LRB-

-RRB-

-LCB-

-RCB-

g

-LRB-

-RRB-

size

-RCB-

fun

-LRB-

-RRB-

-LCB-

x

-LRB-

-RRB-

new

-RCB-

nested

-LRB-

-RRB-

-LRB-

-RRB-

g

-LRB-

-RRB-

-LRB-

x

-LRB-

-RRB-

-RRB-

works

So

the

general

rule

is

that

a

case

is

applicable

at

some

formal

argument

position

if

some

ancestor

of

the

actual

argument

is

known

to

inherit

from

the

formal?s

specializer

according

to

the

inheritance

relation

recorded

in

the

generic

function

This

is

sensible

because

it

allows

one

to

understand

a

generic

function

-LRB-

like

size

in

the

above

example

-RRB-

in

the

context

in

which

it

was

declared

It

then

behaves

as

it

was

understood

no

matter

where

it

is

used

In

this

sense

the

semantics

for

inheritance

is

static

Procedural

and

ADT

Patterns

In

BeCecil

one

can

program

not

only

OO

patterns

but

also

procedural

and

ADT

patterns

Consider

first

argument

dispatch

BeCecil

has

dynamic

multiple

dispatch

as

its

basic

application

mechanism

that

is

the

particular

invocable

in

a

generic

function

that

is

called

is

based

on

the

run-time

ancestry

of

all

the

actual

arguments

However

if

one

has

an

object

such

as

BeCecil?s

any

that

is

the

ancestor

of

-LRB-

almost

-RRB-

all

others

then

by

specializing

on

any

one

is

effectively

not

specializing

on

that

argument

position

Thus

in

BeCecil

one

can

program

as

in

a

single-dispatch

language

by

always

specializing

on

just

the

first

argument

of

a

case

or

one

can

program

in

a

procedural

style

by

never

specializing

on

any

arguments

The

following

are

thus

examples

in

singly-dispatched

OO

and

procedural

styles

-LRB-

respectively

-RRB-

has

method

-LRB-

first@myClass,

snd@any,

thd@any

-RRB-

-LCB-

-RCB-

has

method

-LRB-

first@any,

second@any,

thd@any

-RRB-

-LCB-

-RCB-

BeCecil

Chambers

Leavens

As

Cook

points

out

-LSB-

Cook

-RSB-

one

characteristic

of

ADT

languages

such

as

Ada

-LSB-

Ada

-RSB-

CLU

-LSB-

Liskov

et

al.

-RSB-

or

Standard

ML

is

that

they

completely

control

the

implementation

of

a

particular

type

of

object

That

is

they

are

able

to

guarantee

behavioral

properties

of

objects

of

a

given

type

because

they

control

the

ability

to

create

and

modify

objects

of

that

type

However

usually

objects

in

such

languages

are

not

extensible

-LRB-

i.e.

there

is

no

concept

of

inheritance

-RRB-

The

information

hiding

used

in

our

previous

-LRB-

OO

-RRB-

examples

always

involved

hiding

generic

functions

-LRB-

especially

for

storage

tables

-RRB-

This

allows

one

to

change

data

structures

at

will

and

also

to

enforce

representation

invariants

It

thus

gives

information

hiding

but

does

not

prevent

impersonation

-LSB-

Morris

-RSB-

since

a

client

can

always

create

a

subclass

of

a

given

class

and

override

all

the

methods

that

it

would

otherwise

inherit

To

see

this

consider

the

following

code

which

declares

an

object

that

inherits

from

-LRB-

of

Section

-RRB-

If

the

specifications

of

the

methods

initialize

intensity

and

paint

include

a

requirement

that

they

do

not

loop

forever

then

their

specifications

are

not

satisfied

when

their

first

argument

is

bad

even

though

bad

inherits

from

Thus

behavioral

properties

can

not

be

guaranteed

to

hold

for

all

objects

that

inherit

from

object

bad

inherits

initialize

has

method

-LRB-

b@bad,

-RRB-

-LCB-

initialize

-LRB-

b

f

-RRB-

-RCB-

loop

forever

intensity

has

method

-LRB-

b@bad

-RRB-

-LCB-

intensity

-LRB-

b

-RRB-

-RCB-

loop

forever

paint

has

method

-LRB-

b@bad,

-RRB-

-LCB-

paint

-LRB-

b

r

-RRB-

-RCB-

loop

forever

Languages

like

Ada

or

CLU

are

able

to

guarantee

such

behavioral

properties

because

they

are

not

extensible

that

is

in

such

a

language

one

can

implement

a

type

and

prohibit

a

client

from

creating

instances

except

by

using

some

defined

interface

BeCecil

also

allows

this

style

of

programming

If

the

name

of

a

class

is

hidden

then

clients

can

not

create

instances

directly

Clients

also

can

not

override

methods

for

subclasses

of

the

class

because

clients

will

not

be

able

to

declare

subclasses

at

all

This

style

of

coding

trades

extensibility

for

guaranteed

control

over

instances

For

example

the

following

shows

how

by

hiding

the

name

one

can

make

a

class

that

is

like

but

prevents

imposters

Note

that

the

acceptor

for

the

generic

function

intensity

has

been

moved

inside

the

hide

declaration

since

otherwise

it

could

not

specialize

on

hide

private

declarations

object

field

scale

of

sugared

version

of

the

previous

declaration

of

scale

in

public

declarations

inherits

initialize

has

method

-LRB-

-RRB-

-LCB-

scale

-LRB-

c

-RRB-

truncate

-LRB-

multiply

-LRB-

min

-LRB-

max

-LRB-

intensity

-RRB-

-RRB-

-RRB-

-RRB-

c

-RCB-

gf

has

method

-LRB-

-RRB-

-LCB-

initialize

-LRB-

new

intensity

-RRB-

-RCB-

intensity

has

method

-LRB-

-RRB-

-LCB-

divide

-LRB-

mkFloat

-LRB-

scale

-LRB-

c

-RRB-

-RRB-

-RRB-

-RCB-

intensity

has

acceptor

-LRB-

-RRB-

v

-LCB-

initialize

-LRB-

c

v

-RRB-

-RCB-

paint

has

method

-LRB-

-RRB-

-LCB-

-RCB-

end

The

trade-off

between

extensibility

and

such

control

over

subclasses

and

creation

of

instances

is

perhaps

not

absolute

One

can

imagine

a

language

in

which

subclasses

could

not

override

methods

of

their

BeCecil

Chambers

Leavens

superclasses

or

a

more

complex

language

than

BeCecil

in

which

the

code

for

a

subclass?s

methods

would

have

to

provably

satisfy

the

specification

of

the

superclass

But

this

trade-off

does

seem

fundamental

in

languages

where

subclasses

have

unlimited

ability

to

change

inherited

behavior

and

behavioral

specifications

are

not

an

enforced

part

of

the

program

text

In

summary

BeCecil

allows

one

to

program

in

an

ADT

style

that

gives

every

bit

as

much

control

over

instances

of

a

class

as

one

would

have

in

a

language

like

Ada

or

CLU

When

doing

so

one

gives

up

extensibility

but

that

is

no

worse

than

in

such

ADT

languages

Indeed

BeCecil

is

more

flexible

because

within

a

hide

declaration

one

can

use

subclassing

on

the

hidden

class

even

though

clients

can

not

do

so

Finally

in

BeCecil

one

can

program

in

either

an

ADT

style

or

an

OO

style

and

both

styles

can

be

used

in

the

same

program

BeCecil

Chambers

Leavens

Syntax

Overview

Sugars

and

Examples

for

the

BeCecil

Type

System

In

this

section

we

give

an

overview

of

the

BeCecil

type

system

We

first

present

the

syntax

of

BeCecil

with

its

type

annotations

give

a

brief

overview

of

the

main

ideas

then

describe

some

sugars

and

small

examples

Finally

we

describe

some

subtle

points

of

the

type

system

All

this

should

give

the

reader

a

feel

for

the

type

system

before

the

details

are

presented

in

Appendix

C

-LSB-

Chambers

Leavens

-RSB-

Syntax

The

syntax

of

BeCecil

with

types

is

given

in

Figure

The

syntax

for

generic

function

attributes

has

type

annotations

added

to

formal

parameters

and

a

type

annotation

for

return

types

Also

there

are

several

new

declaration

forms

and

a

syntax

for

type

expressions

Brief

Overview

A

type

error

in

BeCecil

occurs

when

a

program

applies

a

generic

function

to

a

tuple

of

actual

arguments

and

the

generic

function

either

has

no

case

that

is

applicable

to

the

actuals

or

has

more

than

one

applicable

case

but

not

a

unique

most-specific

one

-LSB-

Chambers

Leavens

-RSB-

If

the

first

kind

of

error

-LRB-

message

not

understood

-RRB-

can

occur

the

generic

function

is

incomplete

If

the

second

kind

of

error

-LRB-

message

ambiguous

-RRB-

can

occur

the

generic

function

is

inconsistent

The

BeCecil

type

system

is

designed

to

statically

prevent

such

type

errors

The

philosophy

behind

the

type

system

is

to

leave

the

dynamic

semantics

of

the

language

unchanged

To

this

end

the

central

notions

of

the

type

system

are

found

only

in

the

static

semantics

and

have

no

run-time

effect

To

allow

additional

flexibility

classes

are

not

considered

to

be

types

and

inheritance

is

independent

of

subtyping

Type

information

in

BeCecil

is

largely

declared

not

inferred

although

the

generic

function

types

of

objects

are

inferred

from

the

information

given

as

annotations

to

formal

arguments

and

return

types

of

method

and

storage

table

attributes

To

keep

the

type

system

simple

there

is

no

parametric

polymorphism

thus

the

only

kind

of

polymorphism

supported

is

subtype

polymorphism

Declarations

for

the

Type

System

There

are

four

new

declarations

in

the

typed

version

of

BeCecil

The

first

of

these

is

the

type

declaration

which

declares

names

for

user-defined

types

For

example

the

following

declares

a

new

type

named

Point

type

Point

Since

user-defined

type

names

are

intended

to

describe

ADTs

they

are

considered

to

have

implicit

behavioral

specifications

Hence

two

such

declarations

always

produce

different

types

even

if

they

declare

the

same

name

in

different

contours

To

achieve

this

each

declared

type

name

is

given

a

unique

identity

within

any

contour

in

which

it

is

visible

Since

user-defined

type

names

have

implicit

behavioral

specifications

subtyping

among

type

names

is

declared

not

inferred

For

example

the

following

declares

that

Point

is

a

subtype

of

Top

-LRB-

used

as

the

supertype

of

all

user-defined

types

in

our

examples

-RRB-

and

that

ColorPoint

is

a

subtype

of

Point

and

Color

Point

subtypes

Top

ColorPoint

subtypes

Point

ColorPoint

subtypes

Color

The

subtype

relation

among

types

is

the

extension

of

this

declared

direct

subtyping

relation

to

a

reflexive

and

transitive

relation

BeCecil

does

not

require

that

this

relation

be

antisymmetric

BeCecil

Chambers

Leavens

P

RDS

B

Program

RDS

D

Recursive-Declaration-Sequence

B

RDS

E

Block

D

Declaration

object

I

object

allocates

a

new

object

named

I

inherits

inheritance

directly

inherits

from

CN

has

GF

extension

CN

to

include

the

methods

of

GF

hide

RDS

in

D

end

hide

the

declarations

of

RDS

are

only

visible

to

the

D

type

I

type

new

named

type

TN

subtypes

T

subtype

TN

is

a

subtype

of

T

CN

conforms

T

conformance

CN

has

the

type

T

GF

Generic-Function

attributes

I

identifier

the

methods

and

tables

of

I

method

-LRB-

F

-RRB-

T

-LCB-

B

-RCB-

method

like

l

a

block

abstraction

storage

-LRB-

F

-RRB-

E

T

storage

table

new

table

initialized

to

value

of

E

acceptor

-LRB-

F

-RRB-

I

T

-LCB-

B

-RCB-

acceptor

can

process

an

assignment

with

value

I

combination

favored

over

F

I

CN

T

Formal

argument

T

Type

expression

TN

type

name

a

user-defined

type

-LRB-

T

-RRB-

Tn

invocable

with

arguments

T

returns

Tn

-LRB-

T

-RRB-

Tn

assignable

with

key

arguments

T

and

value

Tn

exact

-LCB-

ET

-RCB-

exact

all

information

about

an

object?s

generic

function

conjunction

glb

of

types

disjunction

lub

of

types

TN

I

Type-Name

ET

Exact-Type

for

a

generic

function

-LRB-

CT

-RRB-

Tn

exact

invocable

with

arguments

CT

returns

Tn

-LRB-

CT

-RRB-

Tn

exact

assignable

with

key

arguments

CT

and

value

Tn

CT

CN

T

Class-and-Type

CN

I

Class-Name

E

Expression

I

class

name

evaluates

to

the

object

denoted

by

CN

-LRB-

AA

-RRB-

application

evaluates

operator

then

operands

left-to-right

-LRB-

AA

-RRB-

En

assignment

with

key

AA

and

value

En

sequence

evaluates

then

AA

Actual-Argument

E

undirected

applicabile

if

inherits

from

specializer

E

@CN

directed

applicable

if

also

a

CNi

inherits

from

specializer

Figure

Syntax

for

BeCecil

with

type

checking

aspects

added

The

nonterminal

I

is

an

identifier

BeCecil

Chambers

Leavens

The

connection

between

the

world

of

objects

and

the

world

of

types

is

established

by

a

conformance

declaration

Conformance

is

a

relation

between

objects

and

types

which

says

that

the

object

has

the

given

type

For

example

the

following

declaration

says

that

the

object

conforms

to

the

type

Point

This

declaration

makes

a

prototype

-LRB-

or

concrete

object

-RRB-

it

can

be

used

in

any

place

that

any

other

object

that

conforms

to

Point

can

be

used

conforms

Point

Conformance

of

formal

parameters

to

types

as

well

as

conformance

of

the

results

of

methods

to

types

is

asserted

with

the

usual

colon

-LRB-

:-RRB-

notation

For

example

the

following

is

the

extension

declaration

for

the

mkPoint

method

mkPoint

has

method

-LRB-

-RRB-

Point

-LCB-

-RCB-

Several

conformance

declarations

may

be

given

for

the

same

object

Thus

an

object

may

have

several

types

For

example

the

following

declarations

say

that

myColorPoint

conforms

both

to

the

type

Point

and

the

type

Color

myColorPoint

conforms

Point

myColorPoint

conforms

Color

An

object

may

conform

to

a

type

either

directly

or

indirectly

Direct

conformance

relationships

are

declared

in

the

program

text

as

above

For

example

myColorPoint

directly

conforms

to

Point

Indirect

conformance

relationships

take

subtyping

into

account

The

phrase

CN

conforms

to

T

means

that

either

CN

directly

conforms

to

T

or

that

CN

directly

conforms

to

some

type

and

is

a

subtype

of

T.

For

example

myColorPoint

conforms

to

Top

Note

that

if

inherits

from

CN

and

CN

conforms

to

T

this

does

not

mean

that

conforms

to

T

inheritance

relationships

have

nothing

to

do

with

conformance

and

subclasses

are

not

required

to

be

subtypes

nor

vice

versa

Not

every

object

has

to

be

declared

to

conform

to

a

user-defined

type

It

is

perfectly

legitimate

to

give

no

conformance

declarations

for

an

object

Such

an

object

is

then

abstract

in

the

sense

that

it

can

not

be

used

as

an

object

in

expressions

The

type

expressions

in

BeCecil

are

inductively

defined

with

user-defined

type

names

as

the

basis

There

are

three

kinds

of

types

that

directly

describe

the

generic

function

value

of

an

object

The

most

familiar

is

the

invocable

type

which

consists

of

a

list

of

argument

types

an

arrow

-LRB-->-RRB-

and

a

return

type

For

example

the

following

declares

that

the

generic

function

equal

can

be

called

with

two

point

arguments

and

returns

a

boolean

equal

conforms

-LRB-

Point

Point

-RRB-

boolean

The

assignable

type

is

written

with

a

list

of

types

that

describe

the

key

an

assignment

symbol

-LRB-

=-RRB-

and

a

type

that

describes

the

value

being

assigned

For

example

the

following

declares

that

the

generic

function

y

can

process

an

assignment

with

a

single

key

of

type

Point

and

a

value

of

type

int

y

conforms

-LRB-

Point

-RRB-

int

The

final

kind

of

type

that

describes

the

generic

function

value

of

an

object

is

an

exact

type

This

consists

of

the

keyword

exact

and

a

set

of

exact

invocable

and

assignable

types

each

of

which

contains

information

about

the

class

of

their

formal

arguments

For

example

the

following

declares

a

variable

and

explicitly

gives

its

exact

type

gf

myVar

myVar

has

storage

-LRB-

-RRB-

int

myVar

conforms

exact

-LCB-

-LRB-

-RRB-

int

-LRB-

-RRB-

int

-RCB-

Exact

types

contain

information

about

each

and

every

case

for

an

object

Hence

an

object

may

only

conform

to

one

exact

type

The

exact

types

of

all

objects

declared

in

a

program

are

inferred

by

BeCecil

from

the

type

BeCecil

Chambers

Leavens

annotations

given

for

method

and

storage

and

acceptor

attributes

of

extension

declarations

This

helps

make

the

language

less

error-prone

since

conformance

declarations

to

exact

types

such

as

the

one

above

are

redundant

It

also

helps

make

the

language

more

extensible

since

writing

down

an

exact

type

for

an

object

means

that

it

can

not

be

extended

with

any

more

cases

However

it

is

sometimes

useful

to

write

down

an

exact

type

for

a

formal

argument

since

an

identifier

can

only

be

used

as

a

generic

function

attribute

if

it

conforms

to

an

exact

type

The

type

system

also

has

conjunction

-LRB-

greatest-lower-bound

-RRB-

types

written

with

an

ampersand

-LRB-

-RRB-

and

disjunctive

types

-LRB-

least-upper-bound

-RRB-

types

written

with

a

vertical

bar

-LRB-

-RRB-

The

conjunction

S&T

is

the

least

specific

type

that

subtypes

both

S

and

T

This

type

is

different

than

any

user-defined

type

if

S

and

T

are

not

ordered

by

the

subtyping

relation

One

use

of

a

conjunctive

type

is

collapsing

several

conformance

declarations

into

one

For

example

the

first

two

declarations

below

are

equivalent

to

the

third

x

conforms

-LRB-

Point

-RRB-

int

x

conforms

-LRB-

Point

-RRB-

int

x

conforms

-LRB-

Point

-RRB-

int

-LRB-

Point

-RRB-

int

The

disjunction

S

T

is

the

most

specific

type

that

is

a

supertype

of

both

S

and

T

While

subtyping

for

user-defined

type

names

is

declared

subtyping

for

generic

function

types

is

structural

Exact

types

have

no

interesting

subtypes

-LRB-

because

there

is

no

way

that

the

information

could

be

more

exact

-RRB-

However

an

exact

type

can

be

translated

into

a

supertype

that

is

a

conjunction

of

inexact

generic

function

types

For

example

suppose

that

the

type

system

has

inferred

that

the

exact

type

of

x

is

the

following

exact

-LCB-

-LRB-

Point

-RRB-

int

-LRB-

Point

-RRB-

int

-RCB-

Then

the

exact

type

information

for

x

can

be

forgotten

by

passing

to

the

following

supertype

-LRB-

Point

-RRB-

int

-LRB-

Point

-RRB-

int

Because

exact

types

for

generic

functions

are

inferred

and

because

they

have

inexact

types

as

supertypes

it

is

not

normally

necessary

to

declare

that

generic

functions

conform

to

inexact

generic

function

types

However

such

declarations

do

have

their

uses

in

particular

when

declaring

the

types

of

abstract

-LRB-

deferred

-RRB-

methods

or

storage

tables

that

are

to

be

implemented

for

all

objects

that

conform

to

a

given

type

For

example

the

type

of

the

generic

function

if

would

be

declared

as

follows

enabling

the

type

system

to

check

that

it

is

implemented

for

all

objects

that

conform

to

the

type

boolean

-LRB-

Such

conformance

declarations

are

similar

to

the

signature

declarations

in

Cecil

-LSB-

Chambers

Chambers

Leavens

-RSB-

-RRB-

if

conforms

-LRB-

boolean

-LRB-

-RRB-

Top

-LRB-

-RRB-

Top

-RRB-

Top

As

a

complete

example

we

show

the

typed

version

of

the

Point

example

from

Section

-LRB-

without

the

use

of

any

syntactic

sugars

-RRB-

type

Point

Point

subtypes

Top

object

inherits

any

conforms

Point

is

a

prototype

object

equal

equal

inherits

equal

has

method

-LRB-

-RRB-

boolean

-LCB-

and

-LRB-

equal

-LRB-

x

-LRB-

-RRB-

x

-LRB-

-RRB-

-RRB-

equal

-LRB-

y

-LRB-

-RRB-

y

-LRB-

-RRB-

-RRB-

-RRB-

-RCB-

object

x

x

inherits

x

has

storage

-LRB-

-RRB-

int

object

y

BeCecil

Chambers

Leavens

y

inherits

y

has

storage

-LRB-

-RRB-

int

object

initialize

inititalize

inherits

initialize

has

method

-LRB-

-RRB-

Point

-LCB-

x

-LRB-

p

-RRB-

i

y

-LRB-

p

-RRB-

j

p

-RCB-

object

mkPoint

mkPoint

inherits

mkPoint

has

method

-LRB-

-RRB-

Point

-LCB-

object

res

res

inherits

res

conforms

Point

initialize

-LRB-

res

x

y

-RRB-

-RCB-

The

way

that

the

type

system

infers

generic

function

types

and

checks

applications

only

allows

one

to

pass

actual

arguments

to

a

case

if

they

conform

to

its

declared

argument

types

Therefore

each

formal?s

specializer

and

declared

type

independently

constrain

what

kinds

of

arguments

can

be

passed

to

it

Thus

a

formal?s

specializer

need

not

conform

to

its

declared

type

For

example

one

can

write

the

following

even

though

any

does

not

conform

to

int

object

double

double

inherits

double

has

method

-LRB-

x@any:int

-RRB-

int

-LCB-

plus

-LRB-

x

x

-RRB-

-RCB-

Client-side

and

Implementation-side

Checks

Type

checking

can

be

divided

into

two

parts

-LSB-

Chambers

Leavens

-RSB-

client-side

checks

and

implementation-side

checks

Client-side

checks

are

principally

that

each

generic

function

application

-LRB-

and

assignment

-RRB-

is

type-correct

by

comparing

the

types

of

the

actuals

and

the

type

of

the

generic

function

Other

such

checks

are

that

the

type

of

the

body

of

a

method

conforms

to

the

declared

result

type

of

the

method

Such

type

checks

are

straightforward

except

for

applications

that

use

directed

actuals

For

directed

actuals

the

generic

function

must

be

statically

known

so

that

its

exact

type

and

inheritance

relation

can

be

used

to

check

that

all

possible

tuples

of

objects

which

match

the

actual

argument

types

will

find

a

unique

mostspecific

method

Implementation

side

checks

are

that

for

each

declared

object

for

each

invocable

type

-LRB-

T

-RRB-

Tr

to

which

that

object

conforms

and

for

each

tuple

of

argument

objects

that

conforms

to

T

the

object?s

set

of

invocables

has

at

least

one

-LRB-

completeness

-RRB-

and

no

more

than

one

-LRB-

consistency

-RRB-

invocable

that

is

applicable

to

the

actuals

furthermore

the

tuple

of

arguments

must

conform

to

the

types

of

this

invocable?s

formals

and

its

result

type

must

be

a

subtype

of

the

result

type

of

Tr

-LRB-

conformance

-RRB-

A

similar

check

must

also

be

made

for

each

object

and

each

assignable

type

-LRB-

T

-RRB-

Tr

to

which

each

object

conforms

In

the

following

example

consider

implementation-side

checks

for

the

declared

objects

bar

and

f

The

object

bar

does

not

conform

to

any

invocable

or

assignable

type

and

thus

trivially

passes

the

implementation-side

checks

The

object

f

conforms

to

the

invocable

type

-LRB-

Bar

-RRB-

int

There

is

just

one

tuple

of

objects

-LRB-

bar

-RRB-

that

conforms

to

the

tuple

of

argument

types

and

it

is

such

that

the

single

method

given

for

f

is

applicable

Furthermore

this

method

has

the

required

return

type

Hence

this

example

satisfies

the

implementation-side

checks

type

Bar

BeCecil

Chambers

Leavens

object

bar

bar

inherits

any

bar

conforms

Bar

object

f

f

inherits

f

has

method

-LRB-

x@bar:Bar

-RRB-

int

-LCB-

-RCB-

It

is

interesting

to

see

how

implementation-side

checking

effectively

checks

that

each

subtype

has

appropriate

methods

to

satisfy

the

usual

rules

for

structural

subtyping

Suppose

the

following

declarations

are

added

to

the

above

example

type

Foo

object

foo

foo

inherits

any

foo

conforms

Foo

Foo

subtypes

Bar

really

Does

the

example

still

pass

the

implementation-side

type

checks

with

these

additional

declarations

No

because

now

there

is

a

tuple

of

objects

-LRB-

foo

-RRB-

that

conforms

to

the

tuple

of

argument

types

for

f

but

for

which

there

is

no

applicable

method

However

if

foo

were

declared

to

inherit

from

bar

then

the

method

would

be

applicable

so

the

checks

would

be

passed

Alternatively

one

could

fix

the

example

by

declaring

another

method

for

f

such

as

the

one

below

f

has

method

-LRB-

y@foo:Bar

-RRB-

int

-LCB-

-RCB-

one

way

to

fix

the

above

example

Another

interesting

aspect

of

the

implementation-side

checks

is

how

they

enforce

a

monotonicity

-LSB-

Reynolds

-RSB-

regularity

-LSB-

Goguen

Meseguer

-RSB-

or

consistency

-LSB-

Agrawal

et

al.

-RSB-

condition

on

the

types

of

the

methods

in

a

generic

function

This

condition

says

that

if

a

generic

function

conforms

to

two

types

-LRB-

Tn

-RRB-

Tr

and

-LRB-

Sn

-RRB-

Sr

and

if

for

each

i

Si

is

a

subtype

of

Ti

then

Sr

must

be

a

subtype

of

Tr

To

see

how

this

is

enforced

suppose

that

for

each

i

Si

is

a

subtype

of

Ti

Then

-LRB-

Tn

-RRB-

Tr

is

a

subtype

of

-LRB-

Sn

-RRB-

Tr

by

the

usual

contravariant

subtyping

rule

for

function

types

-LSB-

Cardelli

-RSB-

Therefore

if

an

object

conforms

to

-LRB-

Tn

-RRB-

Tr

it

must

also

conform

to

-LRB-

Sn

-RRB-

Tr

Thus

methods

that

can

be

called

with

a

tuple

of

arguments

of

type

-LRB-

Sn

-RRB-

must

return

a

result

that

conforms

to

Tr

So

any

method

that

is

declared

to

take

a

tuple

of

arguments

of

type

-LRB-

Sn

-RRB-

must

have

a

declared

result

type

Sr

that

is

a

subtype

of

Tr

The

practical

consequence

of

this

condition

is

that

programmers

have

to

be

careful

to

not

make

the

result

types

of

methods

too

specific

relative

to

their

declared

argument

types

For

example

consider

the

following

declarations

object

negate

negate

inherits

negate

has

method

-LRB-

-RRB-

int

-LCB-

-RCB-

these

do

not

type

check

negate

has

method

-LRB-

-RRB-

float

-LCB-

-RCB-

With

these

declarations

the

code

does

not

pass

the

implementation-side

type

checks

because

negate

conforms

to

the

invocable

type

-LRB-

number

-RRB-

int

and

the

last

method

above

does

not

return

an

int

when

passed

a

number

The

code

would

pass

the

checks

if

the

two

methods

both

had

a

declared

return

type

of

number

The

code

would

also

pass

the

type

checks

if

both

the

methods

had

declared

more

specific

argument

types

-LRB-

int

and

float

-RRB-

A

generic

function

can

also

fail

to

pass

the

implementation-side

checks

if

a

more

specific

method

uses

a

more

general

result

type

than

another

method

that

it

specializes

as

in

the

following

example

where

the

second

method

overrides

the

first

for

arguments

that

inherit

from

Again

the

code

would

type

BeCecil

Chambers

Leavens

check

if

both

methods

returned

the

same

type

however

this

example

can

not

be

fixed

by

changing

the

second

method?s

formal

argument

type

to

float

object

truncate

truncate

inherits

truncate

has

method

-LRB-

-RRB-

int

-LCB-

-RCB-

these

do

not

type

check

truncate

has

method

-LRB-

-RRB-

number

-LCB-

-RCB-

Syntactic

Sugars

The

syntactic

sugars

for

the

type

system

add

to

the

sugars

of

Section

except

where

they

are

noted

as

replacements

Typed

Declaration

Sugars

The

first

declaration

sugar

allows

one

to

declare

a

conformance

relationship

at

the

same

time

that

one

declares

several

inheritance

relationships

inherits

CNn

conforms

T

inherits

CNn

conforms

T

Because

of

the

convention

we

have

been

using

of

naming

classes

with

names

of

the

form

and

the

corresponding

type

X

one

often

wishes

for

example

to

declare

that

an

object

inherits

and

conforms

to

X

at

the

same

time

This

is

particularly

useful

for

declaring

instances

The

following

sugar

is

similar

to

one

in

Cecil

that

serves

a

similar

purpose

object

I

isa

TNn

object

I

inherits

conforms

TNn

The

following

sugars

makes

it

easier

to

declare

subtype

relationships

subtypes

TNn

subtypes

subtypes

TNn

type

I

subtypes

TNn

type

I

I

subtypes

TNn

The

following

sugar

makes

it

easier

to

declare

abstract

generic

functions

by

allowing

one

to

declare

the

name

and

its

type

at

the

same

time

This

sugar

relies

on

the

sugar

for

declaring

generic

functions

from

Section

gf

I

conforms

T

gf

I

I

conforms

T

The

following

sugars

are

replacements

for

the

sugars

of

Section

They

add

type

information

to

the

previous

sugars

var

I

T

E

gf

I

I

has

storage

-LRB-

-RRB-

E

T

BeCecil

Chambers

Leavens

fun

I

-LRB-

F

-RRB-

T

-LCB-

B

-RCB-

gf

I

I

has

method

-LRB-

F

-RRB-

T

-LCB-

B

-RCB-

field

I

of

CN

E

gf

I

I

has

storage

-LRB-

-RRB-

E

where

x

is

a

fresh

identifier

Typed

Formal

Argument

Sugars

As

in

Cecil

it

is

convenient

to

be

able

to

write

the

specializer

and

type

information

for

formal

arguments

in

an

abbreviated

form

I

TN

I

TN

Recall

that

if

the

specializer

is

any

it

can

be

omitted

I

T

I

any

T

The

following

allows

one

to

not

mention

the

specializer

when

a

formal

argument

has

an

invocable

type

I

-LRB-

T

-RRB-

Tn

I

-LRB-

T

-RRB-

Tn

For

example

we

have

the

following

expansion

into

BeCecil

ifTrue

has

method

-LRB-

b@:boolean,

c@:

-LRB-

-RRB-

Top

-RRB-

Top

-LCB-

-RCB-

ifTrue

has

method

-LRB-

-LRB-

-RRB-

Top

-RRB-

Top

-LCB-

-RCB-

Typed

Expression

Sugars

The

following

sugar

replaces

the

untyped

version

of

the

sugar

for

new

given

in

Section

new

CN

T

-LCB-

object

I

inherits

CN

conforms

T

I

-RCB-

where

I

is

a

fresh

identifier

When

creating

a

new

object

of

a

type

named

TN

that

is

to

inherit

from

a

class

named

one

can

use

the

following

sugar

new

isa

TN

new

TN

The

expression

sugars

for

the

two

forms

of

let

carry

over

into

the

typed

version

of

BeCecil

if

one

adds

appropriate

type

annotations

based

on

the

minimal

inferred

types

of

the

expressions

involved

Similarly

the

expression

sugar

for

Smalltalk-like

blocks

carries

over

by

adding

the

return

type

Top

to

the

desugared

form

given

in

Section

Some

Small

Examples

In

this

section

we

show

some

small

examples

of

BeCecil

code

with

types

For

purposes

of

giving

examples

we

assume

that

the

following

declarations

are

used

as

the

standard

prelude

for

all

example

programs

from

now

on

We

continue

to

assume

various

other

generic

functions

that

operate

on

numbers

as

well

BeCecil

Chambers

Leavens

the

typed

standard

prelude

type

Top

type

void

subtypes

Top

type

of

methods

that

do

not

want

to

return

anything

object

nothing

conforms

void

nothing

has

method

-LRB-

-RRB-

void

-LCB-

nothing

-RCB-

object

any

inherits

nothing

abstract

superclass

of

all

other

classes

object

inherits

any

type

number

subtypes

Top

type

int

subtypes

number

type

float

subtypes

number

object

inherits

any

object

inherits

object

inherits

object

isa

int

object

isa

int

object

isa

int

object

isa

float

Boolean

We

add

type

declarations

to

the

Booleans

from

Section

as

follows

The

code

has

been

changed

in

places

to

use

the

generic

function

ifExp

instead

of

if

This

is

because

if

can

return

something

of

any

type

and

so

is

only

useful

as

a

statement

-LRB-

when

one

cares

about

type

checking

-RRB-

The

generic

function

ifExp

works

for

booleans

but

if

it

is

to

function

as

a

true

if-expression

then

it

must

be

extended

for

each

type

of

result

However

these

problems

could

easily

be

solved

by

adding

parametric

polymorphism

to

BeCecil?s

type

system

type

boolean

subtypes

Top

object

inherits

any

abstract

class

the

following

generic

functions

are

to

be

implemented

by

conformers

gf

if

conforms

-LRB-

boolean

-LRB-

-RRB-

Top

-LRB-

-RRB-

Top

-RRB-

Top

gf

ifExp

conforms

-LRB-

boolean

-LRB-

-RRB-

boolean

-LRB-

-RRB-

boolean

-RRB-

boolean

gf

not

conforms

-LRB-

boolean

-RRB-

boolean

gf

equal

conforms

-LRB-

boolean

boolean

-RRB-

boolean

implemented

below

fun

ifTrue

-LRB-

b@:boolean,

c@:

-LRB-

-RRB-

Top

-RRB-

Top

-LCB-

if

-LRB-

b

c

nothing

-RRB-

-RCB-

fun

and

-LRB-

b@:boolean,

c@:

-LRB-

-RRB-

boolean

-RRB-

boolean

-LCB-

ifExp

-LRB-

b

c

-LRB-

-RRB-

false

-RRB-

-RCB-

fun

or

-LRB-

b@:boolean,

c@:

-LRB-

-RRB-

boolean

-RRB-

boolean

-LCB-

ifExp

-LRB-

b

true

c

-LRB-

-RRB-

-RRB-

-RCB-

object

true

isa

boolean

true

has

method

-LRB-

-RRB-

boolean

-LCB-

true

-RCB-

if

has

method

-LRB-

b@true:boolean,

c@:

-LRB-

-RRB-

Top

a@:

-LRB-

-RRB-

Top

-RRB-

Top

-LCB-

c

-LRB-

-RRB-

-RCB-

ifExp

has

method

-LRB-

b@true:boolean,

c@:

-LRB-

-RRB-

boolean

a@:

-LRB-

-RRB-

boolean

-RRB-

boolean

-LCB-

c

-LRB-

-RRB-

-RCB-

not

has

method

-LRB-

b@true:boolean

-RRB-

boolean

-LCB-

false

-RCB-

object

false

isa

boolean

false

has

method

-LRB-

-RRB-

boolean

-LCB-

false

-RCB-

if

has

method

-LRB-

b@false:boolean,

c@:

-LRB-

-RRB-

Top

a@:

-LRB-

-RRB-

Top

-RRB-

Top

-LCB-

a

-LRB-

-RRB-

-RCB-

BeCecil

Chambers

Leavens

ifExp

has

method

-LRB-

b@false:boolean,

c@:

-LRB-

-RRB-

boolean

a@:

-LRB-

-RRB-

boolean

-RRB-

boolean

-LCB-

a

-LRB-

-RRB-

-RCB-

not

has

method

-LRB-

b@false:boolean

-RRB-

boolean

-LCB-

true

-RCB-

equal

has

method

-LRB-

x@:boolean,

y@:boolean

-RRB-

boolean

-LCB-

false

-RCB-

equal

has

method

-LRB-

x@true:boolean,

y@true:boolean

-RRB-

boolean

-LCB-

true

-RCB-

equal

has

method

-LRB-

x@false:boolean,

y@false:boolean

-RRB-

boolean

-LCB-

true

-RCB-

collection

The

following

example

shows

how

to

add

type

declarations

to

the

collection

type

that

was

given

previously

Notice

that

does

not

itself

conform

to

any

type

and

hence

is

an

abstract

class

type

collection

subtypes

Top

type

collElem

subtypes

Top

object

inherits

any

abstract

class

gf

isEmpty

conforms

-LRB-

collection

-RRB-

boolean

to

be

implemented

by

conformers

gf

do

conforms

-LRB-

collection

-LRB-

collElem

-RRB-

void

-RRB-

void

this

one

too

fun

length

-LRB-

c@:collection

-RRB-

int

-LCB-

var

res

int

do

-LRB-

c

anon

method

-LRB-

x

collElem

-RRB-

Top

-LCB-

res

-LRB-

-RRB-

plus

-LRB-

res

-LRB-

-RRB-

-RRB-

-RCB-

-RRB-

res

-LRB-

-RRB-

-RCB-

list

In

the

following

notice

how

equal

is

not

declared

as

here

as

it

has

been

declared

above

However

unlike

the

untyped

version

of

this

example

its

type

is

noted

here

type

list

subtypes

collection

type

listElem

subtypes

collElem

object

inherits

any

conforms

listElem

object

inherits

abstract

class

gf

head

conforms

-LRB-

list

-RRB-

listElem

to

be

implemented

by

conformers

gf

tail

conforms

-LRB-

list

-RRB-

list

to

be

implemented

by

conformers

equal

conforms

-LRB-

list

list

-RRB-

boolean

to

be

implemented

by

conformers

do

has

method

-LRB-

c@:list,

b@:

-LRB-

collElem

-RRB-

void

-RRB-

void

-LCB-

if

-LRB-

isEmpty

-LRB-

c

-RRB-

nothing

-LSB-

b

-LRB-

head

-LRB-

c

-RRB-

-RRB-

do

-LRB-

tail

-LRB-

c

-RRB-

b

-RRB-

-RSB-

-RRB-

-RCB-

We

do

not

declare

a

subtype

of

list

for

the

empty

list

as

there

seems

to

be

no

good

reason

to

do

so

Notice

how

the

non-sugared

form

of

formal

arguments

is

used

in

the

code

below

object

isa

list

isEmpty

has

method

-LRB-

n@nil:collection

-RRB-

boolean

-LCB-

true

-RCB-

tail

has

method

-LRB-

n@nil:list

-RRB-

list

-LCB-

-RCB-

head

has

method

-LRB-

n@nil:list

-RRB-

listElem

-LCB-

head

-LRB-

n

-RRB-

-RCB-

loop

forever

nonempty

lists

The

following

gives

the

code

for

with

type

information

added

object

inherits

abstract

class

isEmpty

has

method

-LRB-

-RRB-

-LCB-

false

-RCB-

BeCecil

Chambers

Leavens

cons

As

with

the

empty

list

we

do

not

declare

a

subtype

of

list

for

lists

implemented

by

We

declare

an

initialization

generic

function

to

allow

initialization

of

lists

Recall

that

the

object

is

used

as

the

default

list

element

gf

initialize

conforms

-LRB-

list

listElem

list

-RRB-

void

object

inherits

any

conforms

listElem

object

inherits

conforms

list

hide

field

hd

listElem

of

list

field

tl

list

of

list

in

initialize

has

method

-LRB-

x

listElem

l

list

-RRB-

list

-LCB-

hd

-LRB-

c

-RRB-

x

tl

-LRB-

c

-RRB-

l

c

-RCB-

tail

has

method

-LRB-

-RRB-

list

-LCB-

tl

-LRB-

l

-RRB-

-RCB-

head

has

method

-LRB-

-RRB-

listElem

-LCB-

hd

-LRB-

l

-RRB-

-RCB-

tail

has

acceptor

-LRB-

-RRB-

list

-LCB-

tl

-LRB-

l

-RRB-

-RCB-

head

has

acceptor

-LRB-

-RRB-

listElem

-LCB-

hd

-LRB-

l

-RRB-

-RCB-

end

fun

cons

-LRB-

x

listElem

l

list

-RRB-

list

-LCB-

initialize

-LRB-

new

list

x

l

-RRB-

-RCB-

equal

has

method

-LRB-

x@:list,

y@:list

-RRB-

boolean

-LCB-

false

-RCB-

equal

has

method

-LRB-

x@nil:list,

y@nil:list

-RRB-

-LCB-

true

-RCB-

equal

has

method

-LRB-

-RRB-

boolean

-LCB-

and

-LRB-

equal

-LRB-

hd

-LRB-

x

-RRB-

hd

-LRB-

y

-RRB-

-RRB-

anon

method

-LRB-

-RRB-

boolean

-LCB-

equal

-LRB-

tl

-LRB-

x

-RRB-

tl

-LRB-

y

-RRB-

-RRB-

-RCB-

-RRB-

-RCB-

Adding

type

information

to

the

interval

list

example

of

Section

is

left

as

an

exercise

for

the

reader

link

Since

BeCecil

does

not

have

parametric

polymorphism

using

the

type

list

results

in

a

loss

of

information

about

the

type

of

the

elements

in

the

list

since

when

extracted

they

are

only

known

to

have

the

type

listElem

Hence

the

following

type

is

sometimes

useful

as

will

be

seen

in

the

alist

example

below

type

link

subtypes

Top

object

inherits

any

conforms

link

object

conforms

link

hide

field

nxt

link

of

link

in

initialize

has

method

-LRB-

l@:link,

next@:link

-RRB-

link

-LCB-

nxt

-LRB-

l

-RRB-

next

l

-RCB-

gf

next

next

has

method

-LRB-

l@:link

-RRB-

link

-LCB-

nxt

-LRB-

l

-RRB-

-RCB-

next

has

method

-LRB-

l@:link

-RRB-

v

link

-LCB-

nxt

-LRB-

l

-RRB-

v

-RCB-

end

BeCecil

Chambers

Leavens

alist

The

following

example

one

way

to

implement

association

lists

shows

some

interesting

uses

of

private

inheritance

and

subtyping

in

the

hidden

declarations

is

made

to

inherit

from

and

to

subtype

link

Notice

also

that

is

also

made

to

conform

to

the

alist

type

type

alist

subtypes

collection

type

key

subtypes

Top

object

conforms

key

type

value

subtypes

collElem

object

conforms

value

conforms

alist

do

has

method

-LRB-

c@nil:alist,

b@:

-LRB-

collElem

-RRB-

void

-RRB-

void

-LCB-

nothing

-RCB-

object

inherits

conforms

alist

hide

isa

link

field

ky

key

of

alist

field

vl

value

of

alist

in

initialize

has

method

-LRB-

al@:alist,

k

key

v

value

next@:alist

-RRB-

alist

-LCB-

ky

-LRB-

al

-RRB-

k

vl

-LRB-

al

-RRB-

v

initialize

-LRB-

next

-RRB-

al

-RCB-

isEmpty

has

method

-LRB-

al@:alist

-RRB-

boolean

-LCB-

false

-RCB-

do

has

method

-LRB-

c@:alist,

b@:

-LRB-

collElem

-RRB-

void

-RRB-

void

-LCB-

b

-LRB-

vl

-LRB-

al

-RRB-

-RRB-

do

-LRB-

next

-LRB-

al

-RRB-

b

-RRB-

-RCB-

gf

assoc

assoc

has

method

-LRB-

k

key

al@nil:alist,

v

value

-RRB-

value

-LCB-

v

-RCB-

assoc

has

method

-LRB-

k

key

al@:alist,

v

value

-RRB-

value

-LCB-

var

res

value

v

if

-LRB-

equal

-LRB-

k

ky

-LRB-

al

-RRB-

-RRB-

-LSB-

res

-LRB-

-RRB-

vl

-LRB-

al

-RRB-

-RSB-

-LSB-

res

-LRB-

-RRB-

assoc

-LRB-

k

next

-LRB-

al

-RRB-

v

-RRB-

-RSB-

-RRB-

res

-LRB-

-RRB-

-RCB-

end

fun

acons

-LRB-

k

key

v

value

next@:alist

-RRB-

alist

-LCB-

initialize

-LRB-

new

alist

k

v

next

-RRB-

-RCB-

Named

Subtypes

of

Generic

Function

Types

In

BeCecil

user-defined

type

names

can

be

thought

of

as

having

implicit

behavioral

specifications

attached

The

following

example

shows

how

to

declare

a

type

that

is

supposed

to

represent

integer-valued

functions

that

square

their

arguments

type

squarer

subtypes

-LRB-

int

-RRB-

int

One

declares

that

a

generic

function

conforms

to

this

type

explicitly

as

follows

Note

that

if

an

object

was

declared

to

conform

to

squarer

without

having

an

integer-valued

method

it

would

not

pass

the

implementation-side

checks

gf

square

conforms

squarer

square

has

method

-LRB-

x@:int

-RRB-

int

-LCB-

times

-LRB-

x

x

-RRB-

-RCB-

BeCecil

Chambers

Leavens

Although

the

type

system

does

not

check

that

square

satisfies

the

implicit

behavioral

specification

it

does

propagate

knowledge

about

what

objects

have

been

asserted

to

conform

to

type

squarer

For

example

the

function

defined

below

requires

its

f

argument

to

conform

to

squarer

fun

-LRB-

a@:int,

b@:int,

c@:int,

-RRB-

boolean

-LCB-

equal

-LRB-

plus

-LRB-

f

-LRB-

a

-RRB-

f

-LRB-

b

-RRB-

-RRB-

f

-LRB-

c

-RRB-

-RRB-

-RCB-

For

example

the

following

application

would

type

check

-LRB-

square

-RRB-

Some

Details

The

type

system

of

BeCecil

deals

with

the

following

features

not

discussed

in

-LSB-

Chambers

Leavens

-RSB-

directed

actual

arguments

extensible

generic

functions

first-class

generic

functions

hide

declarations

and

nested

contours

with

local

inheritance

object

and

extension

declarations

Directed

actual

arguments

are

handled

by

requiring

applications

with

directed

actual

arguments

to

be

to

statically-known

generic

functions

This

is

in

the

spirit

of

OO

languages

which

do

not

allow

one

to

extract

arbitrary

methods

of

objects

and

call

them

The

information

that

is

used

to

type

check

such

an

application

consists

of

the

exact

type

information

for

the

generic

function

and

the

inheritance

relation

that

was

closed

with

the

generic

function

when

it

was

created

This

allows

the

type

system

to

mimic

the

dynamic

semantics

For

the

purpose

of

extending

a

generic

function

cases

can

be

extracted

from

an

object

if

the

object?s

exact

type

is

known

-LRB-

its

identity

is

not

required

-RRB-

This

is

the

main

reason

for

having

exact

types

in

the

syntax

of

type

expressions

First-class

generic

functions

are

handled

by

including

types

for

them

in

the

language

The

type

checking

rules

are

well-known

and

straightforward

Hide

declarations

themselves

cause

no

difficulty

for

the

type

system

other

than

the

fact

that

they

introduce

nested

contours

which

do

cause

problems

We

discuss

these

problems

below

Nested

contours

in

BeCecil

require

careful

attention

if

they

are

not

to

make

the

type

system

unsound

and

if

they

are

to

be

useful

To

help

keep

the

type

system

simple

and

understandable

the

type

system

is

designed

so

that

it

does

not

use

any

information

from

nested

contours

other

than

their

type

correctness

when

checking

a

recursive

declaration

sequence

To

put

this

another

way

the

type

system

assumes

that

the

only

objects

and

inheritance

relationships

that

it

needs

to

consider

are

those

declared

either

in

the

contour

where

the

objects

and

generic

function

attributes

it

is

checking

are

declared

or

in

surrounding

contours

but

not

those

in

nested

contours

However

this

assumption

might

make

the

type

system

unsound

because

in

a

nested

contour

one

could

declare

that

a

new

object

conforms

to

an

argument

type

when

the

new

object

does

not

inherit

from

the

set

of

objects

that

were

assumed

to

conform

to

that

type

-LRB-

types

acquiring

new

conformers

-RRB-

thus

causing

incompleteness

or

when

the

new

object

inherits

from

two

objects

that

were

assumed

to

conform

to

that

type

and

were

assumed

to

not

have

common

descendents

-LRB-

relating

unrelated

conformers

-RRB-

causing

inconsistency

BeCecil

Chambers

Leavens

Our

names

for

these

problems

are

given

in

the

parenthetical

remarks

in

each

of

the

above

bullets

Note

that

the

above

problems

possibly

in

combination

are

the

only

ways

that

type

unsoundness

might

arise

due

to

nested

contours

-LRB-

assuming

that

the

implementation-side

checks

for

the

surrounding

contour

are

carried

out

correctly

and

that

client-side

checking

is

done

as

usual

-RRB-

Thus

the

main

difficulty

in

designing

a

sound

type

system

for

BeCecil

is

preventing

these

problems

without

rendering

nested

contours

useless

To

illustrate

the

problem

of

types

acquiring

unknown

conformers

consider

the

following

-LRB-

type

incorrect

-RRB-

BeCecil

block

In

the

block

the

generic

function

equal

seems

to

be

completely

implemented

-LRB-

if

one

considers

only

the

top-level

declarations

-RRB-

because

there

is

an

implementation

for

the

only

object

that

conforms

to

its

argument

type

However

the

assumption

that

only

objects

that

inherit

from

conform

to

the

type

T

is

falsified

in

the

body

of

the

function

nested

because

is

a

object

that

conforms

to

T

and

it

does

not

inherit

from

type

T

gf

equal

conforms

-LRB-

T

T

-RRB-

boolean

object

inherits

any

conforms

T

equal

has

method

-LRB-

-RRB-

boolean

-LCB-

true

-RCB-

fun

nested

-LRB-

-RRB-

T

-LCB-

object

inherits

any

conforms

T

-RCB-

equal

-LRB-

nested

-LRB-

-RRB-

-RRB-

not

understood

To

illustrate

the

problem

of

relating

unrelated

conformers

consider

the

following

-LRB-

type

incorrect

-RRB-

block

The

top-level

recursive

declaration

sequence

is

checked

as

usual

using

information

in

that

contour

so

it

seems

that

the

generic

function

equal

is

implemented

consistently

the

argument

will

either

inherit

from

Origin

or

Red

but

not

both

as

far

as

that

contour

is

concerned

But

in

the

function

nested

at

the

end

the

object

does

inherit

from

both

objects

Thus

the

call

to

equal

although

seemingly

fine

results

in

a

message

ambiguous

error

type

Comparable

gf

equal

conforms

-LRB-

Comparable

Comparable

-RRB-

boolean

type

ImPoint

subtypes

Comparable

points

that

are

not

necessarily

mutable

object

Origin

inherits

any

conforms

ImPoint

equal

has

method

-LRB-

-RRB-

boolean

-LCB-

true

-RCB-

type

Color

subtypes

Comparable

object

Red

inherits

any

conforms

Color

equal

has

method

-LRB-

-RRB-

boolean

-LCB-

true

-RCB-

var

myImPoint

ImPoint

Origin

fun

nested

-LRB-

-RRB-

void

-LCB-

object

inherits

Red

Origin

conforms

ImPoint

Color

myImPoint

-LRB-

-RRB-

nothing

-RCB-

nested

-LRB-

-RRB-

equal

-LRB-

myImPoint

-LRB-

-RRB-

myImPoint

-LRB-

-RRB-

-RRB-

ambiguous

Our

idea

for

making

the

type

system

sound

and

thus

turning

these

run-time

errors

into

type

errors

is

to

simply

prevent

both

of

these

problems

from

happening

To

do

this

for

each

declared

type

name

TN

the

type

system

tracks

two

pieces

of

information

To

prevent

the

problem

of

types

acquiring

new

conformers

it

tracks

the

set

of

objects

that

are

known

to

conform

to

TN

in

the

recursive

declaration

sequence

in

which

it

was

declared

this

set

is

called

the

conformers

of

TN

To

prevent

the

problem

of

related

unrelated

BeCecil

Chambers

Leavens

conformers

it

tracks

the

inheritance

relation

of

the

recursive

declaration

sequence

in

which

TN

was

declared

this

is

called

the

inheritance

relation

of

TN

Like

inheritance

conformance

and

subtyping

are

also

scoped

in

BeCecil

We

say

that

a

relationship

such

as

that

CN

conforms

to

TN

is

visible

in

an

contour

S

if

that

relationship

holds

in

the

type

context

given

by

the

declarations

of

S

-LRB-

and

surrounding

contours

-RRB-

A

declaration

of

an

object

or

type

name

is

visible

in

a

contour

if

it

is

not

shadowed

The

restrictions

needed

for

soundness

in

the

presence

of

nested

contours

are

that

in

every

contour

S

the

following

must

hold

Suppose

that

the

relationship

conforms

to

TN

is

visible

in

S

and

that

the

declaration

type

TN

does

not

appear

in

S

Then

there

must

be

some

object

such

that

is

a

member

of

the

set

of

conformers

of

TN

and

the

relationship

inherits

from

is

visible

in

S.

Suppose

that

the

relationship

conforms

to

TN

is

visible

in

S

and

that

the

declaration

type

TN

does

not

appear

in

S

Then

for

all

objects

and

if

both

and

are

conformers

of

TN

and

if

both

of

the

relationships

inherits

from

and

inherits

from

are

visible

in

S

then

according

to

the

inheritance

relation

of

TN

either

inherits

from

or

vice

versa

The

first

rule

above

can

be

further

simplified

by

omitting

the

check

that

the

declaration

of

the

type

name

does

not

appear

in

the

contour

and

letting

objects

declared

to

conform

in

the

same

contour

as

the

type

name

trivially

satisfy

the

rule

However

the

second

rule

can

not

be

simplified

in

this

way

as

otherwise

multiple

inheritance

would

be

prohibited

In

an

algorithm

implementing

these

rules

one

would

want

to

only

check

new

conformance

relationships

excluding

those

that

were

already

present

in

a

surrounding

contour

As

an

example

of

how

these

rules

permit

one

to

use

inheritance

in

a

nested

contour

consider

the

following

The

example

is

permitted

by

our

rules

as

the

two

ancestors

of

the

object

floppy

declared

within

the

nested

contour

barnum

and

CircusPerf

each

conforms

to

a

different

type

and

the

two

types

are

unrelated

If

however

CircusPerf

was

declared

as

a

subtype

of

within

barnum

then

the

nested

contour

would

be

illegal

type

Elephant

subtypes

Top

object

inherits

any

conforms

Elephant

fun

haul

-LRB-

e@:Elephant,

thing

Top

distance@:int

-RRB-

void

-LCB-

-RCB-

type

CircusPerf

subtypes

Top

object

inherits

any

conforms

CircusPerf

fun

-LRB-

cp@:CircusPerf

-RRB-

int

-LCB-

-RCB-

fun

barnum

-LRB-

-RRB-

void

-LCB-

type

CircusElephant

subtypes

Elephant

CircusPerf

object

floppy

inherits

floppy

conforms

CircusElephant

object

wagon

inherits

any

conforms

Top

haul

-LRB-

floppy

wagon

-LRB-

floppy

-RRB-

-RRB-

-RCB-

barnum

-LRB-

-RRB-

BeCecil

Chambers

Leavens

Related

Work

BeCecil

bears

a

great

deal

of

similarity

to

Cecil

-LSB-

Chambers

Chambers

-RSB-

However

there

are

several

differences

from

Cecil

that

are

worth

pointing

out

The

major

differences

in

the

dynamic

semantics

are

the

presence

in

BeCecil

of

the

hide

declaration

and

block

structure

A

more

minor

difference

is

the

first-class

nature

of

generic

functions

in

BeCecil

In

BeCecil

assignment

and

generic

functions

are

more

integrated

than

in

Cecil

but

the

ability

to

replace

a

storage

table

with

an

acceptor

and

a

method

follows

Cecil

in

which

a

field

named

f

is

accessed

through

two

methods

f

and

-LRB-

CLOS

Dylan

Self

and

other

languages

also

present

instance

variables

to

clients

as

methods

-RRB-

The

type

system

of

BeCecil

relies

heavily

on

our

previous

work

on

type

systems

for

multimethod

languages

-LSB-

Chambers

Leavens

Chambers

Leavens

-RSB-

The

major

extensions

with

respect

to

that

work

are

the

inclusion

of

block

structure

hide

declarations

and

directed

actual

arguments

-LRB-

which

allows

inheritance

of

methods

-RRB-

Another

difference

is

the

absence

in

BeCecil

of

a

notation

for

declaring

that

objects

are

abstract

or

concrete

There

are

also

some

more

subtle

differences

in

assumptions

for

example

the

type

system

of

BeCecil

does

not

assume

that

there

is

a

type

that

is

the

supertype

of

all

other

types

or

that

there

is

a

class

that

is

the

superclass

of

all

other

classes

-LRB-

although

we

have

used

such

a

type

and

class

in

our

examples

-RRB-

However

Cecil

itself

has

a

type

system

with

parametric

polymorphism

In

the

rest

of

this

section

we

discuss

the

relation

of

BeCecil

to

other

languages

with

multimethods

Abadi

and

Cardelli?s

imperative

object

calculus

and

to

other

OO

languages

with

block

structure

The

l

Calculus

With

respect

to

work

on

multi-method

semantics

the

most

closely-related

work

is

the

l

calculus

-LSB-

Ghelli

Castagna

et

al.

Castagna

et

al.

-RSB-

The

l

calculus

is

a

statically-typed

foundational

calculus

for

multimethod

languages

from

which

BeCecil

draws

several

ideas

In

some

respects

the

l

calculus

is

simpler

than

BeCecil

while

in

other

respects

BeCecil

is

simpler

For

example

in

the

l

calculus

generic

functions

are

applied

differently

than

regular

functions

but

in

BeCecil

there

is

only

one

kind

of

function

On

the

other

hand

BeCecil

allows

new

objects

and

new

inheritance

relationships

to

be

declared

even

in

nested

scopes

In

the

l

calculus

the

classes

-LRB-

which

are

also

types

-RRB-

and

their

inheritance/subtyping

relationships

are

considered

to

be

constants

-LRB-

predeclared

-RRB-

Although

in

BeCecil

is

used

only

in

declarations

as

a

way

to

combine

generic

function

attributes

it

performs

a

similar

function

to

the

operator

in

the

l

calculus

To

make

this

point

more

clearly

we

show

how

the

combination

operator

of

the

l

calculus

can

be

defined

as

an

expression

sugar

in

BeCecil

As

for

attributes

this

combination

takes

the

cases

of

both

expressions

but

for

those

that

clash

-LRB-

have

the

same

specializers

-RRB-

only

the

cases

of

the

second

generic

function?s

methods

remain

in

the

result

Note

that

the

result

of

such

an

expression

has

an

exact

type

in

BeCecil

and

so

it

can

be

used

in

further

combination

expressions

just

as

in

the

l

calculus

-LCB-

object

I

inherits

I

has

I

-RCB-

where

I

is

a

fresh

identifier

The

l

calculus

also

has

a

way

to

write

a

generic

function

with

no

methods

This

is

another

sugar

in

BeCecil

BeCecil

Chambers

Leavens

empty

-LCB-

object

I

inherits

I

-RCB-

A

major

difference

from

BeCecil

is

that

the

l

calculus

does

not

deal

with

mutation

In

some

sense

the

l

calculus

is

indifferent

to

the

presence

of

operators

such

as

assignment

being

a

calculus

that

is

primarily

concerned

with

generic

functions

and

their

invocation

However

the

semantics

of

the

l

calculus

would

have

to

change

to

allow

for

mutable

storage

One

way

this

could

be

done

is

shown

in

the

l

calculus

-LSB-

Castagna

-RSB-

In

this

calculus

there

are

locations

which

have

reference

types

-LRB-

much

as

in

ML

-RRB-

-LRB-

The

l

calculus

also

has

conversion

functions

which

are

used

to

create

specializable

locations

this

permits

the

modeling

of

covariantly-specialized

instance

variables

It

is

unclear

whether

this

can

be

modeled

in

BeCecil

but

there

seems

no

obvious

way

to

do

it

as

the

type

system

would

need

to

be

changed

-RRB-

The

type

system

for

BeCecil

uses

several

ideas

that

are

also

used

in

type

system

of

the

l

calculus

Like

the

l

calculus

BeCecil

does

not

allow

for

dynamic

inheritance

and

its

typing

rules

are

based

on

a

declared

subtyping

relation

between

atomic

types

The

emphasis

on

generic

function

typing

and

the

subtyping

rules

for

generic

functions

are

adapted

from

the

l

calculus

It

is

interesting

to

compare

the

treatment

of

generic

function

types

in

BeCecil

and

the

l

calculus

The

l

calculus

types

for

generic

functions

are

most

closely

related

to

the

exact

types

in

BeCecil

However

the

l

calculus

does

not

permit

a

generic

function

type

to

have

supertypes

that

are

single

arrow

types

-LRB-

the

types

of

non-overloaded

functions

-RRB-

because

in

the

l

calculus

generic

functions

are

applied

differently

than

regular

functions

In

BeCecil

since

there

is

only

one

kind

of

function

and

an

exact

type

has

single

arrow

types

as

supertypes

In

BeCecil

one

may

also

forget

exact

type

information

about

a

generic

function

using

subsumption

one

first

translates

the

exact

type

into

an

inexact

type

and

then

one

may

use

a

rule

that

is

the

same

as

the

rule

for

subtyping

generic

function

types

in

the

l

calculus

In

BeCecil

there

are

no

dynamic

consequences

to

this

forgetting

process

-LRB-

that

is

each

case

in

the

generic

function

is

still

used

exactly

as

before

-RRB-

The

l

calculus

also

allows

supertypes

of

generic

function

types

however

forgetting

information

about

branches

can

have

dynamic

consequences

because

the

type

indexes

in

a

generic

function

type

are

used

to

select

a

particular

method

The

difference

in

the

treatment

of

generic

function

types

reflects

a

more

fundamental

difference

in

the

two

type

systems

in

BeCecil

classes

and

types

are

distinguished

as

well

as

inheritance

and

subtyping

The

l

calculus

does

not

make

these

distinctions

and

thus

its

type

system

is

not

separated

from

its

dynamic

semantics

In

BeCecil

the

dynamic

semantics

is

independent

of

the

type

system

This

separation

does

lead

to

complications

in

the

type

system

of

BeCecil

but

the

result

is

that

BeCecil

gives

programmers

added

flexibility

One

way

to

prove

the

soundness

of

the

BeCecil

type

system

would

be

to

translate

BeCecil

into

the

l

calculus

We

chose

not

to

do

so

as

the

translation

would

not

be

direct

because

the

type

system

of

the

l

calculus

does

not

deal

with

nested

scopes

mutation

or

a

separation

of

types

and

classes

In

summary

although

there

is

a

subset

of

BeCecil

that

is

similar

to

the

l

calculus

the

following

are

the

main

differences

BeCecil

treats

imperative

features

such

as

assignment

BeCecil

has

encapsulation

BeCecil

does

not

require

that

all

objects

and

inheritance

relationships

be

visible

globally

BeCecil

Chambers

Leavens

BeCecil?s

dynamic

semantics

does

not

rely

on

its

type

system

BeCecil

separates

the

concepts

of

types

and

classes

and

subtypes

and

subclasses

Castagna?s

The

language

-LSB-

Castagna

-RSB-

is

a

meta-language

for

reasoning

about

OO

programs

In

particular

is

used

to

describe

the

semantics

of

an

-LRB-

unnamed

-RRB-

toy

OO

language

which

is

a

mix

of

ObjectiveC

and

CLOS

-LRB-

page

-RRB-

While

BeCecil

could

be

compared

either

to

the

toy

language

or

to

BeCecil

is

more

like

and

has

nearly

all

of

the

expressive

power

of

the

toy

language

The

main

differences

between

and

the

l

calculus

are

that

in

one

can

declare

new

classes

and

inheritance/subtyping

relationships

and

there

is

some

provision

for

extending

the

methods

of

a

generic

function

that

allows

for

functional

update

of

existing

methods

-LRB-

i.e.

a

new

generic

function

is

produced

-RRB-

While

one

can

declare

new

classes

and

subtype/inheritance

relationships

in

a

program

all

such

declarations

are

global

to

the

main

computation

unlike

those

in

BeCecil

and

does

not

allow

mutation

In

there

is

also

some

provision

for

reasoning

about

information

hiding

but

unlike

BeCecil

information

hiding

is

not

enforced

-LRB-

In

the

toy

language

however

information

hiding

is

enforced

The

construct

for

information

hiding

is

the

explicit

declaration

of

the

interface

of

a

class

-LRB-

the

protocol

of

its

objects

-RRB-

and

this

is

enforced

by

the

type

system

Thus

information

hiding

in

the

toy

language

is

quite

similar

to

the

hide

mechanism

of

BeCecil

-RRB-

also

has

two

primitives

coerce

and

super

that

are

used

for

inheritance

of

methods

Since

classes

and

types

are

not

separated

in

its

super

mechanism

involves

the

type

system

The

use

of

super

allows

one

to

achieve

an

effect

similar

to

that

of

directed

actuals

in

BeCecil

It

can

be

used

more

freely

than

directed

actuals

in

BeCecil

because

of

the

lack

of

block

structure

in

In

BeCecil

one

could

perform

the

equivalent

of

coerce

by

creating

a

new

proxy

object

however

this

proxy

will

have

a

different

object

identity

than

the

original

object

-LRB-

a

concept

not

present

in

-RRB-

and

thus

will

not

be

wholly

satisfactory

for

the

same

reasons

that

proxy

objects

are

not

wholly

satisfactory

in

standard

OO

languages

Unlike

BeCecil

objects

in

are

records

containing

instance

variables

In

BeCecil

the

fields

of

an

object

are

not

part

of

an

object?s

value

is

also

class-based

BeCecil

does

not

make

a

distinction

between

classes

and

instances

Since

it

is

like

the

l

calculus

shares

several

other

important

differences

from

BeCecil

These

include

the

distinction

between

two

kinds

of

applications

and

the

main

points

summarized

above

Polyglot

Polyglot

a

CLOS-like

database

type

system

-LSB-

Agrawal

et

al.

-RSB-

is

the

only

other

statically-typed

language

with

multimethods

and

mutation

of

which

we

are

aware

The

main

differences

between

Polyglot

and

BeCecil

are

that

Polyglot

requires

that

all

objects

and

inheritance

relationships

be

visible

globally

Polyglot

does

not

separate

the

notions

of

type

and

class

or

subtype

and

subclass

and

Polyglot

does

not

have

a

way

to

declare

the

types

of

generic

functions

apart

from

their

implementations

In

stating

the

type

system

of

BeCecil

in

Appendix

C

we

have

not

tried

to

describe

a

type

checking

algorithm

but

rather

to

describe

rules

that

would

guarantee

type

soundness

However

BeCecil

shares

an

idea

from

the

Polyglot

algorithm

in

that

it

also

divides

the

typechecking

problem

into

implementation-side

and

client-side

checks

In

Polyglot

the

implementation-side

checks

impose

a

consistency

condition

on

the

return

types

of

methods

of

a

generic

function

which

says

that

more

specific

methods

have

more

specific

return

types

-LRB-

This

condition

is

the

same

as

that

used

in

the

category-sorted

algebras

of

Reynolds

-LSB-

Reynolds

BeCecil

Chambers

Leavens

-RSB-

and

in

order-sorted

algebras

-LSB-

Goguen

Meseguer

-RSB-

-RRB-

The

implementation-side

checks

also

require

that

each

set

of

methods

that

are

confusable

-LRB-

i.e.

that

might

handle

the

same

call

-RRB-

is

totally

ordered

by

the

programmer

Client-side

checks

thus

only

need

to

find

a

single

most-specific

multimethod

that

is

applicable

to

the

static

types

of

the

arguments

in

the

call

and

the

consistency

condition

ensures

that

at

run

time

the

result

will

be

a

subtype

of

the

result

type

of

this

method

Compared

to

BeCecil

however

their

type

system

depends

on

a

number

of

restrictive

assumptions

The

methods

of

a

generic

function

must

be

totally

ordered

by

the

programmer

within

each

confusable

set

Graph-based

method

lookup

semantics

found

in

most

object-oriented

languages

with

multiple

inheritance

-LSB-

Snyder

-RSB-

where

the

method

overriding

relationship

only

forms

a

partial

order

can

not

be

handled

BeCecil

does

not

make

any

such

assumption

but

detects

whether

any

ambiguously-defined

messages

are

sent

Because

Polyglot

has

no

way

to

declare

the

type

of

a

generic

function

aside

from

giving

its

methods

and

because

Polyglot

has

no

other

way

to

distinguish

between

concrete

and

abstract

classes

there

is

no

way

to

declare

an

abstract

or

deferred

method

Inheritance

and

subtyping

are

synonymous

in

Polyglot

This

makes

code

less

flexible

because

it

prevents

a

class

from

inheriting

code

from

some

other

class

without

being

required

to

be

a

subtype

-LSB-

Snyder

-RSB-

It

also

means

that

one

can

not

distinguish

the

specializer

of

an

argument

from

its

type

and

thus

one

must

specialize

on

all

arguments

In

BeCecil

one

can

use

a

specializer

that

is

distinct

from

the

formal

argument

type

because

the

specializer

also

does

not

have

to

conform

to

the

argument

type

one

can

use

the

specializer

any

and

thus

effectively

not

specialize

on

that

argument

Kea

Kea

is

a

higher-order

polymorphic

purely-functional

language

supporting

multimethods

-LSB-

Mugridge

et

al.

-RSB-

Objects

in

Kea

contain

various

properties

which

can

be

thought

of

as

fields

unlike

BeCecil

Information

hiding

is

based

on

a

class

mechanism

a

class

has

a

declared

public

interface

and

only

within

a

class

can

other

properties

of

an

object

be

accessed

The

hide

declaration

in

BeCecil

is

similar

Like

Polyglot

code

inheritance

and

subtyping

in

Kea

are

unified

Kea?s

type

checking

includes

the

notion

that

a

collection

of

methods

must

be

exhaustive

and

unambiguous

and

these

notions

appear

in

our

type

system

as

well

The

semantics

of

typechecking

in

Kea

is

also

specified

formally

As

with

Polyglot

our

contribution

in

the

area

of

typechecking

relative

to

Kea

is

that

we

typecheck

several

important

language

features

not

found

in

Kea

including

mutable

state

separate

subtyping

and

inheritance

graphs

-LRB-

which

allow

abstract

classes

-RRB-

and

block

structure

Rouaix?s

Work

Rouaix?s

work

-LSB-

Rouaix

-RSB-

also

describes

a

higher-order

polymorphic

purely-functional

language

This

language

has

no

mutable

state

variables

and

does

not

have

information

hiding

or

block

structure

This

work

uses

a

type

inference

system

that

is

quite

different

than

the

type

system

of

BeCecil

Like

BeCecil

the

language?s

dynamic

semantics

is

specified

separately

from

its

type

system

However

since

there

are

no

type

declarations

there

is

no

way

to

declare

abstract

or

deferred

methods

CLOS

and

Dylan

Both

the

Common

Lisp

Object

System

-LRB-

CLOS

-RRB-

-LSB-

Steele

Paepcke

-RSB-

and

Dylan

-LSB-

Shalit

Feinberg

et

al.

-RSB-

are

languages

with

generic

functions

and

module

systems

Unlike

BeCecil

the

generic

functions

in

these

languages

must

all

have

the

same

number

of

-LRB-

required

-RRB-

arguments

Both

module

systems

provide

name-space

management

allowing

generic

functions

to

be

made

local

or

private

to

packages

-LRB-

although

encapsulation

is

only

advisory

in

Common

Lisp

and

can

be

circumvented

-RRB-

CLOS

allows

one

to

add

methods

to

a

generic

function

either

by

making

a

lexical

binding

in

a

nested

scope

or

by

modifying

the

generic

function

destructively

Dylan

also

allows

one

to

declare

methods

in

nested

scopes

In

these

BeCecil

Chambers

Leavens

languages

inheritance

relationships

can

not

be

scoped

separately

from

objects

and

CLOS

also

allows

inheritance

relationships

to

be

modified

as

the

program

runs

In

both

languages

generic

functions

are

not

integrated

with

objects

as

they

are

in

BeCecil

Both

of

these

languages

are

also

dynamically

typed

Abadi

and

Cardelli?s

Imperative

Object

Calculus

Abadi

and

Cardelli

have

defined

an

imperative

object

calculus

Imp

-LSB-

Abadi

Cardelli

-RSB-

-LSB-

Abadi

Cardelli

chapters

and

-RSB-

that

consists

of

objects

single-dispatch

methods

-LRB-

as

in

Smalltalk

-LSB-

Goldberg

Robson

-RSB-

or

Self

-LSB-

Ungar

Smith

-RSB-

-RRB-

method

update

object

cloning

and

local

definitions

-LSB-

Abadi

Cardelli

page

-RSB-

They

view

method

update

as

a

tamed

version

of

dynamic

inheritance

See

Section

B.

for

why

we

use

storage

tables

instead

of

method

update

in

BeCecil

Although

Imp

and

BeCecil

are

not

really

comparable

because

Imp

does

not

support

multiple

dispatch

or

inheritance

one

can

use

Imp

to

test

of

the

claim

that

BeCecil

is

able

to

express

features

of

the

OO

paradigm

by

translating

Imp

into

BeCecil

The

main

interest

is

how

to

encode

in

BeCecil

Imp

objects

which

are

records

of

methods

since

BeCecil?s

objects

are

not

usually

thought

of

as

containing

their

own

methods

However

one

can

encode

an

Imp

object

as

a

generic

function

that

has

storage

tables

specialized

on

each

label

of

the

record

where

labels

are

considered

to

be

objects

that

do

not

inherit

from

each

other

-LSB-

Castagna

Section

-RSB-

Each

such

storage

table

would

contain

a

generic

function

that

encodes

the

corresponding

method

This

translation

could

be

formalized

with

the

following

sugars

-LRB-

In

the

sugars

a

and

b

are

expressions

x

is

an

identifier

and

l

is

a

label

The

first

is

the

sugar

for

the

Imp

object

expression

which

creates

an

object

and

the

third

is

for

method

replacement

-RRB-

-LSB-

-LRB-

-RRB-

ln

-LRB-

xn

-RRB-

bn

-RSB-

-LCB-

gf

I

I

has

storage

-LRB-

-RRB-

anon

method

-LRB-

-RRB-

-LCB-

-RCB-

I

has

storage

-LRB-

x@ln

-RRB-

anon

method

-LRB-

xn

-RRB-

-LCB-

bn

-RCB-

I

-RCB-

where

x

and

I

are

fresh

a.l

let

I

a

in

-LRB-

I

-LRB-

l

-RRB-

-RRB-

-LRB-

I

-RRB-

a.l

-LRB-

x

-RRB-

b

a

-LRB-

l

-RRB-

anon

method

-LRB-

x

-RRB-

-LCB-

b

-RCB-

clone

-LRB-

a

-RRB-

let

Ia

a

in

-LCB-

gf

I

I

has

Ia

I

-RCB-

where

I

is

different

than

Ia

Note

that

the

anonymous

methods

in

the

translations

do

not

specialize

on

their

argument

This

is

because

the

methods

of

Imp

are

not

multimethods

and

so

have

no

need

of

specialization

We

do

not

include

type

information

in

these

sugars

because

in

Imp

the

types

are

not

declared

and

because

Imp

does

not

have

user-defined

type

names

We

leave

a

closer

connection

between

the

type

systems

as

future

work

The

translation

given

above

assumes

some

way

to

code

labels

as

objects

in

BeCecil

Labels

have

the

property

that

they

are

not

shadowed

by

locally-bound

variables

and

thus

form

a

second

namespace

However

this

can

be

easily

handled

by

name

mangling

in

the

translation

of

labels

into

BeCecil

identifiers

For

example

one

might

translate

labels

and

identifiers

of

Imp

into

BeCecil

as

follows

V

V

V

V

V

V

V

V

V

V

V

V

V

V

V

BeCecil

Chambers

Leavens

l

x

Block

Structure

Few

OO

languages

feature

block

structure

to

any

significant

extent

We

know

of

no

other

statically

typed

OO

languages

with

both

multimethods

and

block

structure

-LRB-

Dylan

allows

one

to

define

methods

in

nested

blocks

but

not

classes

or

inheritance

relationships

CLOS

has

lexical

closures

but

classes

and

inheritance

relationships

are

global

-RRB-

C++

-LSB-

Stroustrup

-RSB-

has

some

amount

of

block

structure

in

that

one

can

declare

classes

within

blocks

However

C++

is

designed

to

carefully

avoid

making

static

closures

for

methods

The

main

OO

languages

that

allow

the

full

use

of

block

structure

are

Simula

-LSB-

Birtwistle

et

al.

-RSB-

and

Beta

-LSB-

Madsen

et

al.

Chapter

-RSB-

In

Beta

there

are

fewer

restrictions

on

the

use

of

block

structure

than

in

Simula

-LSB-

Madsen

et

al.

page

-RSB-

Beta

allows

one

to

define

local

procedures

and

classes

inside

the

bodies

of

other

definitions

including

procedure

and

class

definitions

We

believe

that

BeCecil

supports

all

the

patterns

of

programming

that

can

be

accomplished

in

Beta

in

a

fairly

direct

way

Most

interesting

to

us

is

the

interaction

of

block

structure

and

inheritance

What

happens

when

one

defines

a

class

in

a

local

contour

that

inherits

from

a

class

in

a

surrounding

contour

If

an

instance

of

the

class

is

passed

out

of

the

local

contour

is

this

inheritance

relationship

preserved

In

Beta

the

inheritance

relationship

is

preserved

for

example

messages

sent

to

the

object

are

handled

by

the

superclass

if

the

object?s

own

class

does

not

override

them

Similarly

in

BeCecil

an

inheritance

relationship

declared

in

an

inner

block

is

preserved

by

objects

created

in

that

block

In

BeCecil

the

situation

is

a

bit

more

complex

because

of

the

separation

of

types

and

classes

and

because

inheritance

relationships

can

be

declared

apart

from

the

declaration

of

objects

BeCecil

Chambers

Leavens

Discussion

and

Conclusions

In

this

section

we

discuss

the

expressive

power

of

BeCecil

the

importance

of

separating

the

study

of

a

language?s

dynamic

semantics

from

its

type

system

and

current

work

We

finish

with

some

conclusions

that

describe

the

contributions

of

this

work

The

Expressive

Power

of

BeCecil

BeCecil

is

an

expressive

language

In

particular

it

is

able

to

express

in

a

direct

fashion

typical

patterns

of

OO

programming

including

encapsulating

state

extending

behavior

without

modifying

existing

code

and

subtype

polymorphism

To

demonstrate

this

claim

we

have

presented

several

examples

including

those

that

show

how

to

program

points

with

state

and

object

identity

grayscale

colors

that

encapsulate

state

that

satisfies

an

invariant

grayscale

points

that

inherit

state

and

behavior

from

grayscale

colors

and

points

booleans

and

lists

that

use

subtype

polymorphism

and

abstract

classes

Such

examples

are

standard

in

the

literature

on

OO

programming

e.g.

the

Boolean

example

is

taken

from

Smalltalk

-LSB-

Goldberg

Robson

-RSB-

and

the

list

example

is

taken

from

Cook?s

paper

comparing

ADT

and

OO

styles

-LSB-

Cook

-RSB-

Such

examples

demonstrate

that

BeCecil

qualifies

as

an

OO

programming

language

despite

using

different

mechanisms

than

Smalltalk

or

C++

for

objects

instance

variables

message

passing

classes

and

inheritance

These

new

mechanisms

support

new

patterns

that

are

not

possible

or

feasible

with

single-dispatching

For

example

multimethods

solve

part

of

the

binary

method

problem

-LSB-

Bruce

et

al.

-RSB-

by

giving

efficient

and

direct

access

to

multiple

objects

when

processing

a

message

BeCecil

also

supports

programming

in

an

abstract

data

type

-LRB-

ADT

-RRB-

style

where

one

has

complete

control

over

the

creation

of

instances

of

a

class

while

still

permitting

the

use

of

OO

patterns

within

such

a

class

This

is

not

possible

in

most

purely

OO

languages

and

a

mix

of

styles

like

this

is

not

possible

in

most

ADT

languages

either

However

the

ability

to

mix

styles

comes

not

from

a

large

number

of

features

but

from

the

combination

of

a

very

small

number

of

orthogonal

features

The

Importance

of

Dynamic

Semantics

Although

we

designed

BeCecil

so

that

it

could

be

statically

type

checked

we

also

adopted

as

a

design

principle

that

the

language

should

make

sense

apart

from

its

type

system

While

this

technique

is

not

new

it

does

have

several

benefits

The

main

benefit

is

a

separation

of

concerns

which

allows

each

part

of

the

language

design

to

be

more

highly

polished

A

prime

example

of

this

is

the

hide

declaration

in

BeCecil

The

hide

declaration

can

hide

information

and

can

even

prevent

impersonation

without

any

help

from

the

type

system

In

this

respect

it

differs

from

CLU

-LSB-

Liskov

et

al.

-RSB-

-LRB-

and

from

the

abstype

mechanism

of

Standard

ML

-LSB-

Milner

et

al.

-RSB-

-RRB-

which

achieves

information

hiding

primarily

by

a

difference

between

the

types

of

objects

as

seen

by

the

ADT

implementation

and

its

clients

BeCecil?s

hide

declaration

can

be

seen

as

a

highly

simplified

and

focussed

version

of

the

module

mechanisms

in

CLOS

or

Dylan

which

also

provide

information

hiding

for

multimethod

languages

without

the

aid

of

a

type

system

Another

polished

feature

of

the

BeCecil

dynamic

semantics

is

the

treatment

of

inheritance

in

nested

blocks

Current

Work

The

most

pressing

current

work

is

the

proof

that

the

type

system

of

BeCecil

is

sound

BeCecil

Chambers

Leavens

We

are

also

working

on

a

module

system

for

BeCecil

that

will

allow

separate

typechecking

of

modules

and

combining

independently-developed

modules

-LSB-

Chambers

Leavens

-RSB-

This

module

system

allows

one

module

to

import

another

module

or

to

extend

it

Modules

that

extend

some

other

module

are

called

extension

modules

Extension

modules

can

effectively

insert

declarations

into

the

same

recursive

declaration

sequence

as

the

modules

they

extend

This

is

necessary

because

the

dynamic

semantics

of

BeCecil

can

only

permit

extensions

to

objects

declared

in

the

same

recursive

declaration

sequence

and

because

the

type

system

needs

to

restrict

what

can

be

done

in

nested

blocks

Our

previous

work

did

not

formalize

when

one

needed

to

use

an

extension

module

and

what

privileges

were

gained

by

extension

module

It

is

now

clear

that

the

privilege

gained

by

an

extension

module

is

the

ability

to

effectively

insert

declarations

into

the

extended

module?s

recursive

declaration

sequence

Hence

one

needs

to

use

an

extension

module

to

gain

this

privilege

and

does

not

need

to

otherwise

Conclusions

We

have

described

a

new

and

simple

mechanism

for

information

hiding

in

multimethod

languages

This

mechanism

does

not

compromise

extensibility

and

can

preserve

representation

invariants

BeCecil

also

supports

programming

in

a

mix

of

OO

and

ADT

encapsulation

styles

The

ADT

style

gives

the

ability

to

hide

data

structures

and

preserve

invariants

plus

full

control

over

objects

that

inherit

from

a

given

class

-LRB-

by

giving

up

some

measure

of

extensibility

-RRB-

As

CLOS

and

Dylan

also

have

mechanisms

for

information

hiding

our

contribution

in

this

area

is

the

simplicity

of

our

mechanism

and

the

analysis

of

its

semantics

and

programming

properties

This

analysis

settles

the

problem

of

information

hiding

for

languages

with

multimethods

noted

by

Cook

-LSB-

Cook

-RSB-

BeCecil

also

demonstrates

how

to

achieve

a

high

degree

of

extensibility

in

an

OO

language

with

multimethods

In

BeCecil

generic

functions

can

be

extended

with

new

methods

and

objects

can

be

extended

with

new

inheritance

relationships

by

adding

new

declarations

Existing

declarations

do

not

have

to

be

edited

at

all

We

have

also

shown

that

it

is

possible

for

extensions

to

be

made

in

nested

blocks

where

one

can

declare

new

classes

and

new

inheritance

and

subtyping

relationships

In

a

nested

block

the

extension

mechanisms

of

BeCecil

also

allow

one

to

customize

and

tailor

generic

functions

defined

in

surrounding

blocks

While

the

mechanism

for

combining

the

methods

of

a

generic

function

is

based

on

the

l

calculus

we

have

worked

out

the

details

of

method

combination

in

the

presence

of

nested

blocks

A

main

contribution

is

the

semantics

of

static

inheritance

and

subtyping

in

nested

blocks

which

is

flexible

and

entirely

new

BeCecil

also

demonstrates

how

simple

and

orthogonal

features

can

interact

in

powerful

and

beneficial

ways

For

example

generic

functions

can

subsume

several

other

mechanisms

in

programming

languages

including

procedures

-LRB-

dispatched

on

zero

arguments

-RRB-

singly-dispatched

methods

-LRB-

dispatched

on

one

argument

-RRB-

and

multimethods

The

use

of

generic

functions

and

the

integration

of

generic

functions

and

objects

allows

one

to

program

with

higher-order

procedures

without

sacrificing

simplicity

Storage

tables

which

are

new

with

this

work

are

another

example

of

such

a

feature

as

they

generalize

variables

instance

variables

-LRB-

fields

-RRB-

and

arrays

Finally

BeCecil

provides

another

way

to

understand

OO

programming

languages

because

it

is

an

OO

programming

language

with

very

different

mechanisms

than

the

usual

singly-dispatched

languages

For

example

in

BeCecil

an

object

does

not

contain

either

the

methods

that

apply

to

it

or

its

instance

variables

Despite

this

we

have

shown

that

in

such

a

language

one

can

program

standard

OO

examples

in

a

straightforward

fashion

We

believe

that

the

study

of

such

novel

ways

to

achieve

the

benefits

of

OO

programming

languages

can

only

lead

to

increased

understanding

of

the

design

issues

and

semantics

of

such

languages

BeCecil

Chambers

Leavens

Acknowledgments

This

work

has

been

done

while

Leavens

was

a

visiting

scholar

at

the

University

of

Washington

Leavens?s

research

is

supported

in

part

by

an

NSF

grant

-LRB-

-RRB-

and

by

a

faculty

improvement

leave

from

Iowa

State

Chambers?s

work

is

supported

in

part

by

an

NSF

Young

Investigator

award

-LRB-

-RRB-

and

gifts

from

Sun

Microsystems

IBM

Xerox

Pure

Software

and

Edison

Design

Group

Thanks

to

Michael

Ernst

Wilson

Hsieh

Dave

Grove

and

Vassily

Litvinov

for

comments

and

corrections

on

earlier

drafts

Thanks

also

to

Vassily

for

several

discussions

in

particular

about

the

integration

of

methods

and

state

Thanks

to

other

members

of

the

Cecil

group

for

other

discussions

of

this

work

Thanks

to

the

Computer

Science

and

Engineering

Department

at

the

University

of

Washington

for

their

support

of

Leavens

on

his

faculty

improvement

leave

BeCecil

Chambers

Leavens

References

-LSB-

Abadi

Cardelli

-RSB-

Mart?n

Abadi

and

Luca

Cardelli

An

imperative

object

calculus

Theory

and

Practice

of

Object

Systems

-LRB-

-RRB-

-LSB-

Abadi

Cardelli

-RSB-

Mart?n

Abadi

and

Luca

Cardelli

A

Theory

of

Objects

Springer-Verlag

New

York

-LSB-

Ada

-RSB-

American

National

Standards

Institute

Reference

Manual

for

the

Ada

Programming

Language

ANSI/MIL

STD

February

-LSB-

Agrawal

et

al.

-RSB-

Rakesh

Agrawal

Linda

G.

DeMichiel

and

Bruce

G.

Lindsay

Static

Type

Checking

of

MultiMethods

In

Andreas

Paepcke

editor

OOPSLA

Conference

Proceedings

Phoenix

AZ

October

volume

number

of

ACM

SIGPLAN

Notices

pp.

ACM

New

York

November

-LSB-

Birtwistle

et

al.

-RSB-

Graham

M.

Birtwistle

Ole-Johan

Dahl

Bjorn

Myhrhaug

and

Kristen

Nygaard

SIMULA

Begin

Auerbach

Publishers

Philadelphia

Penn.

-LSB-

Blascheck

-RSB-

G?nther

Blaschek

Object-Oriented

Programming

with

Prototypes

Springer-Verlag

NY

-LSB-

Bobrow

et

al.

-RSB-

Daniel

G.

Bobrow

Kenneth

Kahn

George

Kiczales

Larry

Masinter

Mark

Stefik

and

Frank

Zdybel

CommonLoops

Merging

Lisp

and

Object-Oriented

Programming

In

Norman

Meyrowitz

-LRB-

editor

-RRB-

OOPSLA

Conference

Proceedings

Portland

Oregon

September

volume

number

of

ACM

SIGPLAN

Notices

pp.

ACM

New

York

November

-LSB-

Bruce

et

al.

-RSB-

Kim

Bruce

Luca

Cardelli

Giuseppe

Castagna

The

Hopkins

Object

Group

Gary

T.

Leavens

and

Benjamin

Pierce

On

Binary

Methods

Theory

and

Practice

of

Object

Systems

-LRB-

-RRB-

-LSB-

Cardelli

-RSB-

Luca

Cardelli

A

Semantics

of

Multiple

Inheritance

Information

and

Computation

-LRB-

-RRB-

February/March

An

earlier

version

appeared

in

the

Semantics

of

Data

Types

Symposium

LNCS

pp.

Springer-Verlag

-LSB-

Castagna

et

al.

-RSB-

Giuseppe

Castagna

Giorgio

Ghelli

and

Giuseppe

Longo

A

Calculus

for

Overloaded

Functions

with

Subtyping

In

Proceedings

of

the

ACM

Conference

on

Lisp

and

Functional

Programming

San

Francisco

June

pp.

volume

number

of

LISP

Pointers

ACM

New

York

January-March

-LSB-

Castagna

et

al.

-RSB-

G.

Castagna

G.

Ghelli

and

G.

Longo

A

calculus

for

overloaded

functions

with

subtyping

Information

and

Computation

-LRB-

-RRB-

Academic

Press

February

-LSB-

Castagna

-RSB-

Giuseppe

Castagna

Covariance

and

contravariance

conflict

without

a

cause

ACM

Transactions

on

Programming

Languages

and

Systems

-LRB-

-RRB-

-LSB-

Castagna

-RSB-

Giuseppe

Castagna

A

Meta-Language

for

Typed

Object-Oriented

Languages

Theoretical

Computer

Science

-LRB-

-RRB-

Elsevier

Science

November

-LSB-

Castagna

-RSB-

Giuseppe

Castagna

Integration

of

Parametric

and

ad

hoc

Second

Order

Polymorphism

in

a

Calculus

with

Subtyping

Formal

Aspects

of

Computing

-LRB-

-RRB-

-LSB-

Castagna

-RSB-

Giuseppe

Castagna

Instance

variables

specialization

in

object-oriented

programming

Obtained

from

ftp

-LSB-

Chambers

-RSB-

Craig

Chambers

Object-Oriented

Multi-Methods

in

Cecil

In

O.

Lehrmann-Madsen

editor

ECOOP

Conference

Proceedings

Utrecht

the

Netherlands

June/July

volume

of

Lecture

Notes

in

Computer

Science

pp.

Springer-Verlag

Berlin

-LSB-

Chambers

-RSB-

Craig

Chambers

Predicate

Classes

In

ECOOP

Conference

Proceedings

Kaiserslautern

Germany

July

volume

of

Lecture

Notes

in

Computer

Science

pp.

Springer-Verlag

Berlin

-LSB-

Chambers

-RSB-

Craig

Chambers

The

Cecil

Language

Specification

and

Rationale

Version

Department

of

Computer

Science

and

Engineering

University

of

Washington

December

-LSB-

Chambers

Leavens

-RSB-

Craig

Chambers

and

Gary

T.

Leavens

Typechecking

and

Modules

for

Multi-Methods

In

OOPSLA

Conference

Proceedings

Portland

Oregon

October

volume

number

of

ACM

SIGPLAN

Notices

pp.

ACM

New

York

October

-LSB-

Chambers

Leavens

-RSB-

Craig

Chambers

and

Gary

T.

Leavens

Typechecking

and

Modules

for

Multi-Methods

ACM

Transactions

on

Programming

Languages

and

Systems

-LRB-

-RRB-

November

-LSB-

Chambers

Leavens

-RSB-

Craig

Chambers

and

Gary

T.

Leavens

BeCecil

A

Core

Object-Oriented

Language

with

Block

Structure

and

Multimethods

Semantics

and

Typing

Department

of

Computer

Science

and

Engineering

University

of

Washington

December

Also

Department

of

Computer

Science

Iowa

State

University

TR

December

ftp

the

appendix

sections

only

are

in

ftp

BeCecil

Chambers

Leavens

-LSB-

Clinger

Rees

-RSB-

William

Clinger

and

Jonathan

Rees

-LRB-

Editors

-RRB-

Report

on

the

Algorithmic

Language

Scheme

November

ftp

z

-LSB-

Cook

-RSB-

William

Cook

Object-Oriented

Programming

versus

Abstract

Data

Types

In

J.W.

de

Bakker

W.P.

de

Roever

and

G.

Rozenberg

editors

Foundations

of

Object-Oriented

Languages

REX

School/Workshop

Proceedings

Noordwijkerhout

the

Netherlands

May/June

volume

of

Lecture

Notes

in

Computer

Science

pp.

Springer-Verlag

New

York

-LSB-

Dean

et

al.

-RSB-

Jeffrey

Dean

Greg

DeFouw

David

Grove

Vassily

Litvinov

and

Craig

Chambers

Vortex

An

Optimizing

Compiler

for

Object-Oriented

Languages

In

Proceedings

of

the

ACM

Conference

on

ObjectOriented

Programming

Systems

Languages

and

Applications

-LRB-

OOPSLA

-RRB-

pp.

San

Jose

CA

October

-LSB-

Feinberg

et

al.

-RSB-

Neal

Feinberg

Sonya

E.

Keene

Robert

O.

Mathews

and

P.

Tucker

Withington

The

Dylan

Programming

Book

Addison-Wesley

Longman

Reading

Mass.

-LSB-

Friedman

et

al.

-RSB-

Daniel

P.

Friedman

Mitchell

Wand

and

Christopher

T.

Haynes

Essentials

of

Programming

Languages

McGraw-Hill

New

York

NY

-LSB-

Ghelli

-RSB-

Giorgio

Ghelli

A

Static

Type

System

for

Message

Passing

In

Andreas

Paepcke

editor

OOPSLA

Conference

Proceedings

Phoenix

AZ

October

volume

number

of

ACM

SIGPLAN

Notices

pp.

ACM

New

York

November

-LSB-

Goguen

Meseguer

-RSB-

Joseph

A.

Goguen

and

Jose

Meseguer

Order-Sorted

Algebra

Solves

the

ConstructorSelector

Multiple

Representation

and

Coercion

Problems

In

Symposium

on

Logic

in

Computer

Science

Ithaca

NY

pp.

IEEE

Press

NY

June

-LSB-

Goldberg

Robson

-RSB-

Adele

Goldberg

and

David

Robson

The

Language

and

its

Implementation

Addison-Wesley

Reading

Mass.

-LSB-

Gosling

et

al.

-RSB-

James

Gosling

Bill

Joy

Guy

Steele

Guy

L.

Steele

The

Java

Language

Specification

AddisonWesley

Reading

Mass.

-LSB-

Gunter

-RSB-

Carl

Gunter

Semantics

of

Programming

Languages

MIT

Press

Cambridge

Mass.

-LSB-

Harbison

-RSB-

Samuel

P.

Harbison

Prentice

Hall

Englewood

Cliffs

NJ

-LSB-

Harrison

Ossher

-RSB-

William

Harrison

and

Harold

Ossher

Subject-Oriented

Programming

-LRB-

A

Critique

of

Pure

Objects

-RRB-

In

Andreas

Paepcke

editor

OOPSLA

Conference

Proceedings

Washington

DC

Sept.-October

volume

number

of

ACM

SIGPLAN

Notices

pp

ACM

New

York

October

-LSB-

Leavens

-RSB-

Gary

T.

Leavens

Modular

Specification

and

Verification

of

Object-Oriented

Programs

IEEE

Software

-LRB-

-RRB-

pp.

July

-LSB-

Liskov

et

al.

-RSB-

Barbara

Liskov

Russell

Atkinson

Toby

Bloom

Eliot

Moss

J.

Craig

Schaffert

Robert

Scheifler

and

Alan

Snyder

CLU

Reference

Manual

Volume

of

Lecture

Notes

in

Computer

Science

Springer-Verlag

NY

-LSB-

Madsen

et

al.

-RSB-

Ole

Lehrmann

Madsen

Birger

M?ller

Pedersen

and

Kristen

Nygaard

Object-Oriented

Programming

in

the

Beta

Programming

Language

Addison-Wesley

Reading

Mass.

-LSB-

Meyer

-RSB-

Bertrand

Meyer

Object-Oriented

Software

Construction

Prentice

Hall

New

York

-LSB-

Meyer

-RSB-

Bertrand

Meyer

Eiffel

The

Language

Prentice

Hall

New

York

-LSB-

Milner

et

al.

-RSB-

Robin

Milner

Mads

Tofte

and

Robert

Harper

The

Definition

of

Standard

ML

MIT

Press

Cambridge

MA

-LSB-

Morris

-RSB-

James

H.

Morris

Jr.

Protection

in

Programming

Languages

Communications

of

the

ACM

-LRB-

-RRB-

January

-LSB-

Moon

-RSB-

David

A.

Moon

Object-Oriented

Programming

with

Flavors

In

Norman

Meyrowitz

-LRB-

editor

-RRB-

OOPSLA

Conference

Proceedings

Portland

Oregon

September

volume

number

of

ACM

SIGPLAN

Notices

pp.

ACM

New

York

November

-LSB-

Mugridge

et

al.

-RSB-

W.

B.

Mugridge

J.

G.

Hosking

and

J.

Hamer

Multi-Methods

in

a

Statically-Typed

Programming

Language

Technical

report

Department

of

Computer

Science

University

of

Auckland

Also

appears

in

Pierre

America

editor

ECOOP

Conference

Proceedings

Geneva

Switzerland

July

volume

of

Lecture

Notes

in

Computer

Science

Springer-Verlag

New

York

-LSB-

Nelson

-RSB-

Greg

Nelson

editor

Systems

Programming

with

Prentice

Hall

Englewood

Cliffs

NJ

-LSB-

Ossher

et

al.

-RSB-

Harold

Ossher

Matthew

Kaplan

William

Harrison

Alexander

Katz

and

Vincent

Kruskal

SubjectOriented

Composition

Rules

In

OOPSLA

Conference

Proceedings

pages

Austin

TX

October

-LSB-

Paepcke

-RSB-

Andreas

Paepcke

Object-Oriented

Programming

The

CLOS

Perspective

MIT

Press

BeCecil

Chambers

Leavens

-LSB-

Reenskaug

Anderson

-RSB-

Trygve

Reenskaug

and

Egil

P.

Anderson

System

Design

by

Composing

Structures

of

Interacting

Objects

In

Proceedings

of

the

European

Conference

on

Object-Oriented

Programming

pages

-LSB-

Reynolds

-RSB-

John

C.

Reynolds

Using

Category

Theory

to

Design

Implicit

Conversions

and

Generic

Operators

In

Neil

D.

Jones

-LRB-

editor

-RRB-

Semantics-Directed

Compiler

Generation

Proceedings

of

a

Workshop

Aarhus

Denmark

pp.

Volume

of

Lecture

Notes

in

Computer

Science

Springer-Verlag

NY

-LSB-

Rouaix

-RSB-

Francois

Rouaix

Safe

Run-Time

Overloading

In

Conference

Record

of

the

Seventeenth

Annual

ACM

Symposium

on

Principles

of

Programming

Languages

San

Francisco

CA

pp.

ACM

New

York

-LSB-

Shalit

-RSB-

Andrew

Shalit

The

Dylan

Reference

Manual

The

Definitive

Guide

to

the

New

Object-Oriented

Dynamic

Language

Addison-Wesley

Reading

Mass.

-LSB-

Shilling

Sweeney

-RSB-

John

J.

Shilling

and

Peter

F.

Sweeney

Three

Steps

to

Views

Extending

the

Object-Oriented

Paradigm

In

Norman

Meyrowitz

editor

OOPSLA

Conference

Proceedings

New

Orleans

Louisiana

October

volume

number

of

ACM

SIGPLAN

Notices

pp.

ACM

New

York

October

-LSB-

Snyder

-RSB-

Alan

Snyder

Encapsulation

and

Inheritance

in

Object-Oriented

Programming

Languages

In

Norman

Meyrowitz

-LRB-

editor

-RRB-

OOPSLA

Conference

Proceedings

Portland

Oregon

September

volume

number

of

ACM

SIGPLAN

Notices

pp.

ACM

New

York

November

-LSB-

Steele

-RSB-

Guy

L.

Steele

Jr.

Common

Lisp

The

Language

-LRB-

second

edition

-RRB-

Digital

Press

Bedford

MA

-LSB-

Stroustrup

-RSB-

Bjarne

Stroustrup

The

C++

Programming

Language

Second

Edition

Addison-Wesley

Reading

Mass.

-LSB-

Ungar

Smith

-RSB-

David

Ungar

and

Randall

B.

Smith

Self

The

Power

of

Simplicity

In

Norman

Meyrowitz

editor

OOPSLA

Conference

Proceedings

Orlando

FLorida

volume

number

of

ACM

SIGPLAN

Notices

pp.

ACM

New

York

December

-LSB-

Van

Hilst

Notkin

-RSB-

Michael

Van

Hilst

and

David

Notkin

Using

C++

Templates

to

Implement

Role-Based

Designs

In

Proceedings

of

International

Symposium

on

Object

Technologies

for

Advanced

Software

March

-LSB-

Winskel

-RSB-

Glynn

Winskel

The

Formal

Semantics

of

Programming

Languages

Foundations

of

Computer

Science

Series

MIT

Press

Cambridge

Mass.

-LSB-

Wirfs-Brock

Johnson

-RSB-

Rebecca

J.

Wirfs-Brock

and

Ralph

E.

Johnson

A

survey

of

current

research

in

objectoriented

design

Communications

of

the

ACM

-LRB-

-RRB-

September

block structure
encapsulation
generic functions
information hiding
inheritance
multimethods
static typechecking
subtyping

bececil language
object-oriented programming languages