Suppose you needed to some simulations before a business implements their ideas, what would you pick? Suppose you needed a program that understands natural language, what language would you pick? 5. Better understanding of programming languages will improve your code and reduce bugs What is the appropriate implementation of error handling in your program? What can you do in your code to improve maintainability? Suppose we want to produce the reverse of a string in Java. What is good/bad about this approach? static String reverse(String str) { String rev = ""; for (int i = 0; i < str.length(); i++) rev = str.charAt(i) + rev; return rev; } String origStr = "abcdef"; String revStr = reverse(origStr); ?? Terminology for Programming Language Categorization Imperative statements that change a program's variables Structured imperative without GOTO statements Procedural a step-wise structured process where the program specifies how to do something Functional uses functions which given a particular value of X always returns the same result. Imperative FORTRAN (uses GOTO statement) Procedural COBOL, PL/I, C, Python Functional LISP (although most implementations provide nonlocals) LISP examples: (COND ((> X Y) X) (T Y)) (+ (* L 2) (* W 2)) Object-oriented C++, Java, Python Logical SQL, Prolog SQL example: select Student.Id, Student.Name from Student, Enrollment where Student.Id = Enrollment.Id AND Enrollment.CourseNr = "CS3723";
B 15 25 A 15 50 Output with dynamic scope (non-locals are impacted by calling sequence): B 15 55 A 15 55 Parameter Passing Arguments (i.e., actual parameters) - passed to a function. Arguments might be identifiers, constants or expressions (which might involve function calls) Parameters (i.e., formal parameters) - represent the arguments in the called function Parameter transmission techniques: By Value - the value of the argument is passed and becomes the value of the formal parameter By Reference - conceptually a pointer (usually the location of the argument) is transmitted; function can modify the argument; often called by address parameter passing By Name - transmit an unevaluated argument, allowing the called function to evaluate it Note: many languages use By Value, but pass references to objects (i.e., the pointer's value is copied not the address of the variable). You will find many incorrect sites which incorrectly state a language has by reference parameter passing since it passes a reference. It is better to call this by value object reference. C arrays are passed by reference by default, everything else is passed by value; however, an address of the argument can be passed by using the & operator // call determineMinMax(gradeM, iNumEntries, &dMin, &dMax); // function declaration void determineMinMax(double gradeM[], int iNumEntries , double *pdMin, double *pdMax) { … if (gradeM[i] > *pdMax) *pdMax = gradeM[i]; … } PL/I uses by reference instead of the programmer dereferencing a parameter in the called function, the compiler did that under the covers. /* call */ determineMinMax(gradeM, iNumEntries, min, max); /* function declaration */ determineMinMax: PROC (gradeM, iNumEntries, min, max); DCL gradeM(*) FLOAT, iNumEntries FIXED BIN, min FLOAT, max FLOAT; … IF gradeM(i) > max max = gradeM(i); … END determineMinMax; Java uses by value and by value object reference
when an argument is a reference to an object, a copy of that reference is passed. (This is not by reference parameter passing.) Translation and Execution This topic is frequently known as compilation vs interpretation. Many traditional languages (COBOL, FORTRAN, PL/I, C) have most of these steps in translation: Preprocess - converts preprocessor directives to source language statements Compile - generates assembly language from the source language code Assemble - generates machine instructions for the assembly language statements Link - resolves external references to create an executable Another approach is to do all translation/execution at runtime. With interpretation, the language is quickly parsed and executed instead of having formal compilation steps prior to execution. Java uses a hybrid of compilation and interpretation. C (PL/I has the same steps) Preprocessor translates #include, #define, #ifndef directives into their corresponding C code Compiler generates appropriate assembly language (depending on hardware and operating system) Assembler generates machine code Linker resolves external references (e.g., global extern references to global extern function calls to the address of those functions) LISP No preprocessor, compiler, assembler, linker Interpreted at runtime from a prefix syntax using a LISP Virtual Machine Java No preprocessor Compiler generates appropriate bytecodes (non-architecture specific assembly-like language) Bytecodes are interpreted at runtime a Java Virtual Machine When necessary for performance, some implementations will translate to machine code prior to execution or dynamically during execution Operations and Sequence Control These provide the essential framework within which operations and data are combined. Some characteristics of operations: syntax notation (prefix, infix) precedence extensibility number of operands explicit vs implicit operations explicit vs implicit operands explicit vs implicit results invariant vs generic Infix notation: perimeter = 2 * width + 2 * length; // rectangle perimeter = l1 + l2 + l3 + l4; // four-sided polygon What are some shortcomings of notation? ?? How would we represent a substring operation which requires 3 operands (string, start, length)? ?? Prefix notation in LISP: (+ (* 2 width) (* 2 length)) (+ l1 l2 l3 l4)
Sequence Control In most languages, flow is linearly downward statement by statement. We have statements which can alter that flow: Conditional - if, if-then-else, case constructs Iteration - loop, repetition (e.g., for) Subprogram - macros, functions, recursion, parallel, event-based Interrupts - an unusual event altering flow PL/I case statement examples: /* Example 1 */ SELECT (TRANSACTION.COMMAND); WHEN ('DEPOSIT') CALL DEPOSIT(TRANSACTION, ACCOUNT); WHEN ('WITHDRAWAL') CALL WITHDRAWAL(TRANSACTION, ACCOUNT); WHEN ('INTEREST') CALL ADD_INTEREST(TRANSACTION, ACCOUNT); OTHERWISE DO; PUT SKIP EDIT('INVALID COMMAND: ', TRANSACTION.COMMAND) (A, A); END; END; /* Example 2 */ SELECT; WHEN (TRANSACTION.COMMAND = 'WITHDRAWAL' & ACCOUNT.BALANCE < 0) CALL OVERDRAWN(TRANSACTION, ACCOUNT); WHEN (TRANSACTION.COMMAND = 'DEPOSIT') CALL DEPOSIT(TRANSACTION, ACCOUNT); OTHERWISE CALL WITHDRAWAL(TRANSACTION, ACCOUNT); END; Binding The when a program element is bound to a characteristic or property strongly influences a programming language. Categories of Binding Times Execution Time - during program execution Translation Time (compile time) - bindings performed by the compiler Language Definition Time - when the language was described Language Implementation Time - variations for a particular implementation of the language Execution Time binding of variables to values binding of variables to their locations (e.g., automatics in C) binding of parameters to arguments on function entry for by value and by address parameters on reference for by name parameters Translation Time binding of variables to their data types (C) binding of variables to their structure (C) binding of variables to their locations (static in C, but the actual address is bound by the loader) Language Definition Time meaning of +, -, *, / meaning of if, printf Language Implementation Time ordering of bits (little endian, big endian) size of int, size of long meaning of isalpha in C Object Orientation // C typedef for Student
Although very popular in organizations using IBM mainframes, it didn't have wider appeal. Why? ?? Error Handling The ease of detecting and handling errors influences programming languages. Interrupts - an unusual event, detectable by software or hardware, that may require special processing. Exceptions - events generated by interrupts or other software Some languages (e.g., C++, Java) allow programmer-defined exceptions. Some languages provide extra features to aid in fixing error situations. Visual Basic and PL/I allow control to be returned back to the point of where an error occurred. Interrupts divide by zero invalid address reference (segmentation faults) page fault break points arithmetic overflows/underflows Software-generated Exceptions stack underflow (popping an empty stack) subscript range