Fundamentals of Programming Languages 1. DEFINITIONS... 2 2. BUILT-IN TYPES AND PRIMITIVE TYPES... 3 TYPE COMPATIBILITY... 9 GENERIC TYPES... 14 MONOMORPHIC VERSUS POLYMORPHIC... 16 TYPE IMPLEMENTATION MODELS... 18 IMPLEMENTATION OF STRUCTURED TYPES... 19 3. SCOPE... 23 4. ROUTINES... 26 5. OVERLOADING... 27 A. Bellaachia Page: 1
1. Definitions Attributes: o It is a set of properties used to describe a program entity, e.g., variable and function. o Example: Array: Name, Element type, Index type, Index lower bound, Index upper bound, and address. Variable: Name, Type, and Value. o Five Semantic Attributes of Variables In general, the semantics of variables in programming languages is often described in terms of four attributes. Name: It is the name used to refer to the variable. Type: A description of the set of permissible values for a variable. Scope: The region of program text over which a variable is known. l-value (or location): A location in memory associated with the variable. r-value: Typically, an indirect attribute of a variable; the value stored in the memory location associated with a variable. Descriptors: It is where the values of the attributes of an element are stored. Binding: o It is the process of assigning a value to the attribute of an element. o Binding Time: At what time a value is assigned an attribute. A. Bellaachia Page: 2
There are two types of binding: Static: o A binding is static if it first occurs before run time and remains unchanged throughout program execution. o Static binding occurs at: Compile time: Implementation time: Range of values for an integer. Language definition: Possible operators on strings: and +. Dynamic: o A binding is dynamic if it first occurs during execution or can change during execution of the program. o Dynamic binding occurs at: Run time: Assign a value to a variable. o Stability: Is the assignment of a value fixed or modifiable? 2. Built-in Types and Primitive Types What is a type? Values Operations A. Bellaachia Page: 3
A primitive type mimics hardware units. We call primitive types those types that are not built from other types. Example: Character is a primitive type in C, but String is not. Boolean is not a primitive type in C while it is in Java. Examples: Booleans Integers Reals Characters Benefits: Hides underlying representation Can do type checking at compile time Can resolve overloaded functions at compile time Programmer can specify the accuracy required Data Aggregates and Type Constructors o Definition: An aggregate data type, also called compound object, consists of one or more data type objects. Example: o Arrays: consists of one or more elements of a single data type placed in contiguous locations from first to last. A. Bellaachia Page: 4
o Constructors: It is the method used to create an aggregate data type. Examples: o Cartesian Products o Sequences o Etc. o Cartesian Product: A constructor used to create records and structures Definition: Cartesian product of n sets A1, A2, A3,, An is a set whose elements are ordered n-tuples (a1, a2, a3,, an), where each ak belongs to Ak for 1 k n. Example: o Structure in C o Records in Pascal and Ada. o A C example: #include <stdio.h> typedef struct { char name[30]; int age; char ssn[10]; } person; main (){ person myname = {"Bell", 20, "222222222"}; printf("person Info: \n"); printf("\t\t%s\n\t\t%d\n\t\t%s\n", myname.name,myname.age, myname.ssn); A. Bellaachia Page: 5
} o Mapping Definition: o A mapping is a function from a set of values (domain) to a set of values (range): F: integer -> real Array Constructor: is a mapping from a set of integers (index) to a set of values (content of the array). Example: o Int myarray[5] ={-2,0,- 3,4,300}; MyArray: 0-2 MyArray: 1 0 MyArray: 2-3 MyArray: 3 4 MyArray: 4 300 Another Example: enum Colors {red, white, black, green, blue}; The compiler assigns an integer number to each name in the enumerated type starting from zero. A. Bellaachia Page: 6
o Union and Discriminated Union Union is a constructor that allows objects to be specified by a disjunctive of fields, e.g., field 1 or field 2 or... or field n. An instance object has only one field: Save space. It is up to the programmer to remember which address is valid Example: o Variant records in Pascal o Union structures in C: union mixed { int i; float f; char c; }; union mixed m; m.i = 10; o Powerset: Powerset(T): This is a constructor that creates a variable whose value is a set of elements of type T. T is called the base type. Example: o set type in Pascal o Java APIs: Sets. A. Bellaachia Page: 7
o Sequence: Sequences constructor allows the creation of objects whose number of elements is not specified. Objects will have arbitrary size. Example: sequential files, Vector, List in Java. o Recursion Recursion is a constructor that allows the size of an object to grow dynamically (add or delete elements). Example: Create the structure of a Linked List in C typedef strcut { DoulyLinkedList * previous; Char name[30]; DoulyLinkedList * next; } doublylinkedlist; doublylinkedlist *head; A. Bellaachia Page: 8
Type Compatibility o Definitions: Type checking is the activity of ensuring that the operands of an operator are of compatible types Casting or Coercion: A compatible type is one that is either legal for the operator, or is allowed under language rules to be implicitly converted, by compiler-generated code, to a legal type. A type error is the application of an operator to an operand of an inappropriate type. Static type checking: If all type bindings are static. Dynamic type checking: If all type bindings are dynamic. o Strong Typing & Type Checking A type system is said to be strong if it guarantees not to generate type errors. Strongly typed languages: Languages that have strong type systems. Weakly typed languages: languages that are not strongly typed. Coercion rules weakens the value of strong typing Static Type System: The type of each expression must be known at compile time. Requirements of a static type system include: A. Bellaachia Page: 9
o Only built-in types can be used o All variables are declared with an associate type. o All operations are specified by stating the types of the required operands and the type of the results. Statically Typed Languages are Strongly Typed Languages. A. Bellaachia Page: 10
Compatible Types: o A compatible type is one that is either legal for the operator, or is allowed under language rules to be implicitly converted, by compiler-generated code, to a legal type. o Type compatibility is also called conformance or equivalence. o There are two type compatibility methods: Name compatibility (also called strict compatibility): o Two variables can have compatible types only if they are in either the same declaration or in declarations that use the same type name. o It is highly restrictive. o It is easier to implement. o Ada uses name compatibility. Structure type compatibility: o Two variables have compatible types if their types have identical structures. o It is more flexible. o It is difficult to implement: compare the whole structure instead of just names. o Two types are structurally compatible if: 1. T1 is name compatible with T2; or 2. T1 and T2 are defined by applying the same type constructor to structurally A. Bellaachia Page: 11
compatible corresponding type components. o Examples: 1. Two records or structure types compatible if they have same structure but different field names? 2. Two single-dimensioned array types in a Pascal or Ada program are compatible if they have the same element type but have different subscript ranges? 3. C uses structural compatibility except for structures. A. Bellaachia Page: 12
Type Conversion: o It is needed when the types of an expression are not compatible. o Some programming languages allow automatic conversions (Also called coercion): What would the following C program output? #include <stdio.h> main(){ char c1 = 'a'; int i = 10; i += c1; printf(" The value of i is:%d\n",i); } o Formally, the conversion of a type T 1 to another type T 2 is defined as follows: func: T 1 T 2 For example: T 1 x 1 ; T 2 x 2 ; x 2 = func(x 1 ); o How to use func to convert from another type T 2 to another type T 2? Requirements: Two new functions t 21 and r 12 : t 12 : T 1 T 2 A. Bellaachia Page: 13
r 23 : T 2 T 3 Let x 1 be a variable of type T 1 and y 3 be a variable of type T 3, then apply t 12 to x 1, apply t 23 to the result, and assign it to y 2 : y 3 = t 23 (t 12 ( x 1 ) ) ); Type and Subtype: o A subtype ST of a basic type T (also called parent type or supertype) can be defined as A subset of the values of T Assume that operations of T are inherited by ST o A language supporting subtypes must provide: A way to define subsets of a given type, and Compatibility rules between a subtype and its supertype Example: Ada subtype SUBTYPE Day_Range IS Integer RANGE 0..31; SUBTYPE Year_Range IS Integer RANGE 1901..2099; SUBTYPE natural IS integer range 0..integer'last; SUBTYPE natural IS integer RANGE 0..integer last; SUBTYPE positive IS integer RANGE 1..integer last; Generic Types o It allows functions and ADT to have generic types o How type-checking is done to guarantee type safety? A. Bellaachia Page: 14
o Example: Bind generic types to concrete types at compile-time instantiation. push: stack(t)xt stack(t) pop: stack(t) stack(t)xt length: stack(t) int A. Bellaachia Page: 15
Monomorphic versus Polymorphic o Monorphic: It is a strict type system. o Polymorphic: It is the case where an object can have more than one type o Most practical programming languages have some degree of polymorphism. o Languages deviates form strict monomorphic if they include one of the following: Type equivalence Coercion Subtyping Overloading o Polymorphism classification: universal Parametric (Templates) Inclusion (subtypes) polymorphism overloading Ad hoc coercion A. Bellaachia Page: 16
Ad hoc : functions work on a finite small set of types and may behave differently for each: Overloading Coercion Universal: work uniformly for an infinite set of types, all of which have common structure Parametric Inclusion A. Bellaachia Page: 17
Type Implementation Models o How to represent data objects inside the machine o The implementation of each data object requires two elements: Descriptor: structures used to store the attributes of the data Data object: memory locations to store the actual values o Built-in Primitive types: Integers and reals are supported on most computers They may also provide different sized versions of these types Representations: Descriptor integer sign bit Descriptor real sign bit for mantissa sign bit for exponent k-bit exponent h-bit mantissa A. Bellaachia Page: 18
Implementation of Structured Types o Cartesian product: It is a sequential layout of components. The descriptor contains the following: o The Cartesian product type name and o For each field: Name of the selector Type of the field Reference to the data object Example: type another_type is struct{ float a; int b; }; type sample_type is struct{ int x; another_type y; }; sample_type z; Sample_type Struct x int y another_type struct a float b int Integer value Floating point value Integer value A. Bellaachia Page: 19
o Finite Mapping Allocate storage units for each element component. The descriptor contains the following: o The mapping type name o The name of the domain type o Values for the upper and lower bounds. o The name of the range type o A reference to the first location of the mapping Example: type x_type is float array[0..10]; x_type x; Type x_type 0 Constructor array 1 Index type int Lower bound 0 Upper bound 10 Range type float Reference 10 A. Bellaachia Page: 20
o Union and discriminated union The descriptor of a variable of a union type is the sequence of the descriptors of each component. Example: type x_type = array[0..10] of real; type z_type = record case kind: boolean of true: (a:integer); false: (b:x_type); end; Type Z_type constructor Variant record Selector Kind Type Boolean Case table Boolean value Reference Case table True false Selector b Type X_type Constructor array Selector a Index type Integer Type L. bound 0 reference integer U. bound 10 Range type real Reference A. Bellaachia Page: 21
o Powerset Use bit-mapping to represent a set Use AND for Intersection and OR for union Example: S = {1, 3, 10, 16} 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 0 1 0 1 0 0 0 0 0 0 1 0 0 0 0 0 10 0 0 0 A. Bellaachia Page: 22
3. Scope Definitions: The scope of a variable is the range of statements over which it is visible The scope rules of a language determine how references to names are associated with variables. Example: #include <stdio.h> main( ) { int x, y; printf("please enter a value for x: "); scanf( "%d", &x ); printf("please enter a value for y: "); scanf( "%d", &y ); { // This block used to swap x and y int temp; temp = x; x = y; y = temp; } printf( "x:%d and y:%d\n", x, y ); // printf( "temp:%d\n", temp ); } If you try to execute the last statement in Visual C++, you will get the following error: error C2065: 'temp' : undeclared identifier Non-local variables: The non-local variables of a program unit are those that are visible but not declared in the program. A. Bellaachia Page: 23
Example: #include <stdio.h> float increase_factor = 10.5; main() { float x; printf("please enter a value for x: "); scanf( "%f", &x ); printf( "The input value is: %f\n",x); // increase_factor variable is used but not declared in // main function. printf( "The increased value is: %f\n",x * increase_factor); } Searching: Search declarations, first locally, then in increasingly larger enclosing scopes, until one is found for the given name Main A C D B E A. Bellaachia Page: 24
Scoping types: Static scope binding: The scope of a variable is defined by examining the program code. You do not need to run the program. Dynamic scope binding: o The scope of a variable is defined at runtime. o Example: MAIN { - declaration of x SUB1 { - declaration of x -... call SUB2... } SUB2 {... - reference to x -... }... call SUB1 } MAIN calls SUB1 SUB1 calls SUB2 SUB2 uses x Static scooping: reference to x is to MAIN's x Dynamic scooping: reference to x is to SUB1's x A. Bellaachia Page: 25
4. Routines We will use the term routine to mean: Subprograms: Assembler Subroutines: FORTRAN Procedures: Pascal, Ada Functions: C, LISP Methods: Java, C++ Routine Parts: Declaration: o The Specification of the name, list of formal parameters, and any return type. Body o The list of statements within the definition of the routine. Invocation: o Statement used to call the routine. Routine Attributes: Name Scope: It is similar to variable scope. Type: It is defined by the routine header: Name of the routine, the types of the parameters, and the type of the returned type. L-value: It is the memory area where the body of the routine is stored. R-value: It is the body of the routine. Routine Parameters: Formal parameters: o It is the set of parameters that appear in the routine s definition. Actual parameters: A. Bellaachia Page: 26
o It is the set of parameters that appear in the routine s call. Some programming languages have positional method and named for binding actual parameters to formal parameters in routine calls. Routine Signature: This specifies the types of the parameters and the return type. Activation record: o Data objects associated with local variables (including any parameters) o The relative position (offset) of the data object in the activation record. o Return pointer: It is the address where execution must resume in the calling routine. 5. Overloading Overloading: Method overloading is commonly used to create several methods with the same name that perform similar tasks: public int square (int side); public double square(double side) Java enables methods of the same name to be defined as long as they have different signatures. A C++ Example: #include <iostream.h> int max(int x, int y){ return (x>y?x:y); A. Bellaachia Page: 27
} float max(float x, float y){ return (x>y?x:y); } void main(){ } float a = 4.5; float b = 3.4; cout << max(3,6) << endl; cout << max(a,b) << endl; A. Bellaachia Page: 28