CS 342 Lecture -*- Outline -*- * Types and type checking ** Types -strongly typed (no way to violate representation independence) -no implict coercions (but allows differences in range, scale) => compiler could change range, precision, etc for efficiency -user defined types, "processed at translation time" name equivalence general syntax of full type declarations type FEET is INTEGER range 0..5280; *** fixed point types (besides integer, floating) (more efficient than floating point for some appls.) ------ type DOLLARS is delta 0.01 range 0.00 .. 1_000_000.00; ------ (gives absloute error bound) -messy -types INTEGER, FLOAT are predeclared -numeric types are one of nicest parts of Ada *** Enumeration types and subranges thereof BOOLEAN, CHARACTER predeclared enumeration types names in enumeration types can be overloaded --------- type ANSWER is (TRUE,FALSE,MAYBE); ------------ can say which is meant: ANSWER(TRUE), BOOLEAN(TRUE) B: BOOLEAN := TRUE; --know from context *** arrays semidynamic arrays (size fixed at allocation time) type IT is array(1..N) of INTEGER; -strings are 1-dimensional character arrays subtype POSITIVE is INTEGER range 1..INTEGER'LAST; type STRING is array(POSITIVE range <>) of CHARACTER; name: STRING(1..20); *** records can have default component values ---------- type BIKE is record wheels: INTEGER := 2; maker: STRING; end record; ---------- *** Variants -part of record type (saves space?) -tag must be present and secure (can only change tag by assigning whole record) -in Ada tag is a parameter of type ---------- type LEXEME(GROUP:LEXGROUP) is record case GROUP is when reflex => loc: address; when valex => val: INTEGER; others => null; end record; ---------- *** Dynamic types (pointer types) -no dangling references (heap allocation) => either gc or wasted storage --------- type CELL; --incomplete type LINK is access CELL; type CELL is record VALUE: INTEGER; SUCC: LINK; PRED: LINK; end record; v: LINK := new CELL(0,null,null); --------- *** Packages (modules) -contain declarations of anything that is declarable -no external access, explicit export -own variables (with initialization) ** Type checking name equivalence, with subtypes and derived types => need single declaration (in library unit) for each type *** subtypes place constraints on types, (don't give new types) ------------- subtype INDEX is INTEGER range 1..100; N: INTEGER; I: INDEX; ------------- INDEX is a subtype of INTEGER; (range constraint optional) -as in Pascal subtype is compatible with base type and other subtypes of the base type I:=N; N:=I; --both legal -inherits operations of base type I:= I+1; --inherited operation -another syntax type INDEX is range 1..100; -subtyping is transitive subtype LITTLE_INDEX is INDEX range 1..10; LITTLE_INDEX is a subtype of INTEGER and INDEX. *** derived types inherit operations from base but are not compatible ----------- type PERCENT is new INTEGER range 0..100; P: PERCENT; ----------- not compatible with INTEGER, INDEX I:=P; P:=I; P:= N; --all illegal inherits operations, attributes, functions (user-defined too) P:= P+1; F(P); explict conversions PERCENT(N) INTEGER(P) *** constraints (instead of subranges) range constraints (see above) **** accuracy constraints ---------- FLOAT digits 10 range -1e6 .. 1e6 ---------- **** discriminant constraints (for variants) LEXEME(reflex) -- for variant above **** index constraints can defined unconstrained array types, but to allocate storage need size ---------- type VECTOR is array(INTEGER range <>) of FLOAT; DATA: VECTOR(1..100); DAYS: VECTOR(1..366); ---------- *** Limited types: used within packages (later) -neither assignment nor = is implicitly declared (gives uses chance to define them). = can be defined *** Assignment compatability -lhs and rhs must have same type (i.e., compatible) (not a limited type) this is checked at compile time -runtime checks rhs must belong to subtype of lhs (i.e., satisfy constraint), except for arrays, where allow arrays of same size but different indexes e.g. --------- S1: STRING(1..20); S2: STRING(1..10); S3: STRING(0..9); S1 := S2; --will cause a constraint_error (exception) S2 := S3; --legal --------- ** Overloading --------------- package CHAR_LIST is new LIST(CHARACTER); declare use INT_LIST; use CHAR_LIST; LI: INT_LIST.LIST_TYPE; LC: CHAR_LIST.LIST_TYPE; begin LC := CONS('A',NIL); -- CHAR_LIST.CONS, CHAR_LIST.NIL LI := CONS(1,NIL); -- INT_LIST.CONS, INT_LIST.NIL end; --------------- An expression is legal if one and only one subprogram can be chosen for each operator in the expression. Operator identification relies on: name, number of parameters, types and order of actuals, names of formals (if named associations used), result type (for functions). operator identification can be accomplished in one pass! trade-off of readability vs. writeability (don't know of any principle that applies) ** Position-independent and default parameters (section MacLennan's 8.1) *** parameters can be associated with formals using their names, instead of positions ------- LC := CONS(L => NIL, X => 'A'); LC := CONS('A', L => NIL); ------- Similar to syntax for array, record constructors (1..5 => (1..8 => 0.0)) --matrix TABLE'(5,8,4,1, others => 0) (DAY => 4, MONTH => JULY, YEAR => 1776) *** parameters can have default values --------- function CONS(X: T; L: LIST_TYPE := NIL) return LIST_TYPE; -- can write CONS('A'); --------- *** interaction of position independent parameters and defaults complicates operator identification -overloading is prohibited in subprogram declarations if introduces potential for ambiguity --------- -- following illegal because ambiguous procedure P(X: REAL; Y: REAL := 0.0); procedure P(X: REAL; Y: BOOLEAN := FALSE); --------- P(3.0) is ambiguous -complicated by other kinds of overloading (see text).