Programming Language Concepts: A Comprehensive Overview

Programming Language Concepts

BNF and EBNF

Understand how to describe language features like loops using BNF or EBNF, and how to convert between them. For example:

  • BNF Example: -> + | – |
    -> * | / |
  • EBNF: -> } ->

Semantic Languages

Learn how attribute grammars, operational semantics, denotational semantics, and axiomatic semantics work and their applications.

  • Attribute Grammars: Contain semantic information on parse tree nodes. Used for static semantics specification and compiler design.
  • Operational Semantics: Used for language manuals, textbooks, and teaching programming. Two levels: Natural and Structural. Good for informal descriptions, complex for formal ones.
  • Denotational Semantics: Recursive and the most abstract. Example: s = {, } VARMAP (ij,s) = vj
  • Axomatic Semantics: Used for formal program verification and formal logic. Employs assertions to state relationships and constraints among variables. Example: a=b+1 {a>1} weakest precondition = b>0

Bindings

Understand the workings of static and dynamic binding rules. Binding time refers to when an association between an entity and its attribute (e.g., variable and value) occurs.

  • Static Binding: Occurs before runtime and remains unchanged.
  • Dynamic Binding: Occurs at runtime or changes during execution.

Scoping

Learn how static and dynamic scoping rules work.

  • Static Scoping: Based on program text. Looks for declarations locally, then in larger enclosing scopes until one is found. Variables can be hidden by closer variables with the same name. Ada allows access to hidden values (e.g., unit.name).
  • Dynamic Scoping: Based on the calling sequence. Subprogram calls determine which variable is linked.

Type Equivalence

Understand the difference between structural equivalence and name equivalence.

  • Name Equivalence: Values have the same type based on the fully qualified name of their type (e.g., int a; int b; – both a and b have the “int” type).
  • Structural Equivalence: Values have the same type if their types are structurally equivalent, regardless of the name. Name equivalence implies structural equivalence.

Data Types

Know various data structures (arrays, records, etc.), their advantages and disadvantages, supported data types in different languages, implementation details, type checking mechanisms, strongly typed languages, and the evolution of data types.

  • Primitive Data Types: Not defined in terms of other data types, often reflecting hardware.
  • Strings: Different implementations across languages (e.g., char array in C/C++, primitive in Python, object in Java).
  • Arrays: Different notations and index types across languages (e.g., () in Fortran and Ada, [] in most others).
  • Strong Typing: Type errors are always detected (e.g., Ada, Java, C#).

Expressions and Assignment Statements

Understand various expressions, operator precedence, operator overloading, type conversions and coercions, short-circuit evaluations, and assignment statements.

  • Operator Overloading: Allows operators to have different meanings depending on their operands. Can improve readability but can also lead to confusion and errors.
  • Type Conversions: Explicitly changing the type of a value.
  • Coercions: Implicit type conversions. Can weaken type checking.
  • Short-Circuit Evaluation: Evaluating only as much of an expression as necessary to determine its value.

Control Structures

Know selections, iterations, etc. in languages like Ada, Fortran, Python, and F#.

Ada Example

procedure Arr1 is
   A: array(1..5) of Integer;   
   I: Integer;
begin
   -- Read 'em in.
   for I in 1..5 loop
      Put("> ");
      Get(A(I));
   end loop;

   -- Put 'em out in reverse order.
   Put("[");
   for I in reverse A'Range loop
      Put(A(I));
      if I > A'First then
         Put(' ');
      end if;
   end loop;
   Put_Line("]");
end Arr1;

Fortran Example

real :: v1(3), v2(3), m(3,3)
integer :: i,j
v1(1) = 0.25
v1(2) = 1.2
v1(3) = 0.2

! to the unit matrix
do i=1,3
 do j=1,3
  m(j,i) = 0.0
 end do
 m(i,i) = 2.0

enddo

Python Example

for loop_variable in object:
    loop body
[else
    else clause]

current, next, reset

list = [x ** 2 for x in range(12) if x%3 == 0]
# puts [0,9,36,81] in list

F# Example

let rec forLooop loopBody reps =
if reps <=0 then
    ()
else
    loopBody()
    forLoop loopBody, reps-1

// this is recursive, keeps calling loopbody for the number of reps.

Subprograms

Understand how in, out, and inout parameters work, parameter passing mechanisms (value, reference, name, value/result), language implementations (activation records, static and dynamic links, scoping), displays, etc.

  • Parameter Passing: Different languages use different methods (e.g., pass-by-value in C, pass-by-reference in C++).
  • Activation Records: Data structures that store information about a subprogram’s execution.
  • Static and Dynamic Links: Used to manage the scope of variables in nested subprograms.