200 likes | 361 Views
Approaches to Typing. Programming Languages Robert Dewar. Typing: Why?. There are several different motivations for typing in high level languages Efficiency Error Checking Redundancy Overloading. Efficiency. Compiler can generate better code if it knows exactly what is in each variable.
E N D
Approaches to Typing Programming Languages Robert Dewar
Typing: Why? • There are several different motivations for typing in high level languages • Efficiency • Error Checking • Redundancy • Overloading
Efficiency • Compiler can generate better code if it knows exactly what is in each variable. • Historically that’s where typing comes from • In Fortran • INTEGER I • REAL R • Subroutines have parameters of specified type • Compiler can generate efficient code for exactly the type of data present without any kind of checks. • Types match machine datatypes • For example: 32 bit integers
Error Checking • In a freely typed system (e.g. assembler) • Can add a float to an integer?! • Can compare a string to a float?! • Can use a float as a pointer?! • Can assume a buffer is 1K! • When really it is only 512 bytes?! • Etc.
Error Checking (continued) • Typing prevents errors of this kind • By detecting the error either at compiletime or run-time. • Stronger typing capabilities mean that more errors can be detected. • For instance, the “buffer overrun” • Detected in Ada, but not in C
Redundancy Eliminates Errors • Cannot misspell an identifier • Shuttle_Presure := 1.0 • undefined identifier • possible misspelling of Shuttle_Pressure • Cannot accidentally mix units • Probe_Velocity := Probe_Velocity + Accel; • type mismatch • Probe_Velocity is of type MPH • Accel is of type KPH
Overloading • A = B + C • With typing, we know whether to do an integer or real addition • Obj->Draw • We know which Draw to call based on the type of Obj.
Compile Time vs Run Time • Some typing semantics are compile time • In Fortran, do we do integer or real addition • In Ada, cannot assign Float to Integer • Some typing semantics are run-time • In Ada, subscript out of range • In C++, dynamic dispatch for virtual method
Different Approaches to Typing • Explicit Static Typing at Compile Time • Dynamic Typing at Run Time • Static Typing by Inference at Compile Time
Explicit Static Typing at Compile Time • Code contains explicit declarations • A : Integer; • int *p; • Compiler knows the types • Compiler checks the types at compile time
Run-Time Typing • Type is not determined till run-time but is fixed once it is is determined • B : Integer range 1 .. N; • C : array (Integer range 1 .. N) of integer; • “type” error is now a run-time exception • But some static analysis is possible • Type R is new integer range 1 .. N; • M, K : R; • M := K; -- definitely OK
Run-Time Typing • Type is dynamically modified at run-time • type sp is access String; • A, B : sp; • … • A.all := B.all; -- run-time exception if wrong • Dynamic dispatching is similar case • Q *R; • .. • R->Draw();
Dynamically Typed Languages • Go all the way with run-time typing • SNOBOL-4 is an example • No explicit type declarations • No variable has a fixed type at run-time • Can put any value of any type anywhere • But values are still strongly typed
SNOBOL4 as an Example • No explicit declarations • Variable “declared” by assigning to it • X = 123 ;* X now has integer 123 • X = X + 1 ;* X now has integer 124 • X = “ABC” ;* X now has string “ABC” • X = X “M” ;* X now has string “ABCM” • X = X + 1 ;* run-time error
Type Inference • A3 := B4 + 1; • Q: What type is A3 and B4; • A: Must be integer • if Test1 then … • Q: What type is Test1 • A: Must be Boolean • If we can answer these questions why bother with redundant declarations?
Type Inference Languages • No explicit declarations • Language designed so that all types can be inferred. • Inference involves a chain of reasoning: • A3 := Func (Test1); • Q: What is Func • A: Must be array/function Boolean->Integer • Would be better to have separate notations for functions and arrays!
More on Type Inference • A language with a sound type system is one in which all types can always be inferred in any valid program. • Example of language designed this way is Standard ML. • Note that we still have strong static typing and many of the benefits that come from that.
ML: Example of Type Inference • Types always implied: - val x = 5; (*user input *) val x = 5: int(*system response*) - fun len lis = if (null lis) then 0 else 1 + len (tl lis); val len = fn : ‘a list -> int • Type inference for local entities - x * x * x; val it = 125: int(* it denotes the last computation*)
Limits on Inference • Inference is Structural. Cannot duplicate: • type A is new Integer;type B is new integer;VA : A;VB : B;…VA := 1;VB := 1;VA := VB
Summary • Efficiency Error Checking Redundancy Overloading • Explicit YES YES YES YES • Dynamic NO YES NO YES • Inference YES YES? YES? YES?