Types and Type Safety in Programming Languages, Study notes of Computer Science

The concept of types in programming languages, their importance in ensuring type safety, and the properties of static type systems. It also covers practical issues related to type checking in c++ and java, including liskov substitution principle, covariant and contravariant subtyping, and checked exceptions.

Typology: Study notes

Pre 2010

Uploaded on 07/30/2009

koofers-user-6ih
koofers-user-6ih 🇺🇸

9 documents

1 / 7

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
1
Types
CMSC 631
Reading
Type Safety by Luca Cardelli
Read Sections 1-3 by Tuesday
Read Section 4-6 by Thursday
If you really get into types
Types and Programming Languages
by Benjamin Pierce
What is a type?
A set of values
For example
integers that can be represented using 32-bit signed
representation
floating point numbers represented using 64-bit
IEEE-754 representation
Strings
more types
64-bit floats with units meters
64-bit floats with units feet
64-bit floats with units meters/second
32-bit integers representing a user id
32-bit integers representing length of arrays
of wide characters
32-bit integers representing # of bytes
What types do
Many functions & operators are only
defined to work on certain types
e.g., integer addition
functions and operations might be overloaded
use either static or dynamic resolution
resolve ‘+’ to integer addition, float addition or string
concatenation
Type errors
Applying a function to arguments of the
wrong type is an error
Resolved as:
static error
dynamic error
undefined behavior
pf3
pf4
pf5

Partial preview of the text

Download Types and Type Safety in Programming Languages and more Study notes Computer Science in PDF only on Docsity!

Types

CMSC 631

Reading

• Type Safety by Luca Cardelli

• Read Sections 1-3 by Tuesday

• Read Section 4-6 by Thursday

• If you really get into types

  • Types and Programming Languages

by Benjamin Pierce

What is a type?

• A set of values

  • For example
    • integers that can be represented using 32-bit signed representation
    • floating point numbers represented using 64-bit IEEE-754 representation
    • Strings

more types

• 64-bit floats with units meters

• 64-bit floats with units feet

• 64-bit floats with units meters/second

• 32-bit integers representing a user id

• 32-bit integers representing length of arrays

of wide characters

• 32-bit integers representing # of bytes

What types do

• Many functions & operators are only

defined to work on certain types

  • e.g., integer addition
  • functions and operations might be overloaded
    • use either static or dynamic resolution
      • resolve ‘+’ to integer addition, float addition or string concatenation

Type errors

• Applying a function to arguments of the

wrong type is an error

• Resolved as:

  • static error
  • dynamic error
  • undefined behavior

What makes a programming

language safe?

• An unsafe operation is one that is defined to

have no defined meaning

  • Anything could happen
    • provide root access to script kiddies
  • Might be predictable on some

platforms/implementations

  • for good or ill

Some unsafe behaviors

• Accessing outside the bounds of an array

• Using incorrect format string in scanf/printf

• using an integer as a pointer

Strong type systems

• Prevent undefined behavior due to use of

incorrect types

• Typically coupled with measures to prevent

other unsafe behaviors

• Generally involve substantial static

component

  • some debate as to whether dynamic types really

are a “type system”

What properties should a static

type system have?

  • Be verifiable
    • efficient type checking algorithm
      • JVM runs a type inference and checking algorithm every time it verifies a method
  • Be transparent
    • programmer shouldn’t be flummoxed by type checking algorithm
  • Be enforceable

Why have static types?

• Efficient execution

  • don’t need to check dynamic tag information
    • e.g., can use unboxed ints

• Detecting errors, small and large

  • using integer as a pointer
  • adding meters + feet
  • detecting errors statically is much better than

detecting them during execution

why, continued

• Encourage better abstractions

• Better documentation

  • that is checked at each compilation

co and contra variant subtyping

• Forget method overloading on argument

types for a moment

• class T {

void foo(T t) { … }

T bar () { … }

• class S subtype of T { … }

Does this work?

• class T {

void foo(T t) { … }

T bar () { … }

• class S subtype of T {

void foo(S t) { … }

S bar () { … }

Partway

• foo doesn’t

  • someone who expects a T could invoke foo and

provide T as an argument

  • S’s implementation of foo can’t handle a T

• bar does

  • someone who expects a T could invoke bar and

expect a T to be returned

  • should be able to handle an S

How about this?

• class T {

void foo(S t) { … }

T bar () { … }

• class S subtype of T {

void foo(T t) { … }

S bar () { … }

subtyping rules for functions

• When is (B Æ C) Õ (A Æ D)?

• A Õ B (contravariant arguments)

• C Õ D (covariant return types)

Contravariants typing

is rarely used/available

  • Few, if any, programming languages use

contravariant typing

  • argument types must match exactly in order to override
  • C++ provides covariant return types
  • Java does not
  • return types have to match exactly
  • a mistake, hard to fix now
  • Java has covariant declared exceptions

Java errors

• class A implements Cloneable {

public boolean equals(A a) { … };

public A clone() { … };

Pre and Post conditions

  • class T { // Precondition P // Postcondition Q … foo(…) {…} }
  • class S is a subtype of T { // Precondition P’ // Postcondition Q’ … foo(…) {…} } - P must imply P’ - S can relax preconditions of T - Q’ must imply Q - S can guarantee more than T - P fi P’ and Q’ fi Q

types and conditions similar

• When can Q:R foo(P:A)

• be overridden by Q’:R’ foo’(P’:A’)

• P fi P’ and Q’ fi Q

  • P Õ P’ and Q’ Õ Q

• A Õ A’ and R’ Õ R

Checked Exceptions

• In Java, declared exceptions are checked at

compile time

  • all checked exceptions must be declared
    • runtime exceptions and errors don’t need to be

• In C++, if a method declares that it throws

exceptions

  • runtime check that no other errors are thrown

subtyping of declared exceptions

  • which gives an error?
  • class T {

void foo() throws IOException { … };

void bar() { … };

  • class S extends T {

void foo() { … };

void bar() throws IOException { … };

  • Given /** Search array for value / /* @precondition: a is sorted / /* @postcondition: returns index i s.t. a[i] == value, or -1 if no such value exists */ int search( int [] a, int value);
  • In an overriding function can we
    • a) Change the precondition to true?
    • b) Change the precondition to a is sorted and there exists an i s.t. a[i] = value?
    • c) Change the postcondition so that i == -1 or i is the first index s.t. a[i] == value?
    • d) Change the function so that it throws "NoSuchElementException" rather than returning - when value does not occur in a.

C++ array subtyping

struct A {

int x;

struct B : public A {

int y;

void foo(A a[]) {

a[1].x = 42;

B b[5];

foo(b);

C++ store subtyping

  • class A { … };
  • void swap(A & a1, A & a2) {

A tmp = a1;

a1 = a2;

a2 = tmp;

  • B b; C c; class B : public A { … };
  • class C : public A { … };
  • swap (b,c);