CS 334 Lecture 24
CS 334 Lecture 24
- Criteria for Language Design
- Writeability
- Simplicity
- Uniformity:
- Expressiveness
- Orthogonality & generality
- Clear, unambiguous syntactic and semantic description
- Readability - Modifiability and Maintenance.
- Documentation:
- Lexical and syntactic conventions:
- Not synonymous with wordiness:
- Importance depends on number of programmers.
- Reliability
- Static checks
- Separate (but not independent) compilation
- Minor modifications should not require major changes.
- Clear semantics supporting verification.
- Simplicity of compiler implementation.
- 4. Fast translation
- 5. Efficient object code
- 6. Machine independence:
- Hoare on Designing Programming Languages
- Features:
- Language:
- Principles from MacLennan (on reserve shelf):
- Why a principles of programming languages course:
The language should be easy to master
- bad ex: PL/I & Ada - don't throw in kitchen sink!
If too complex, danger of unexpected interactions, subsetting & (if
redundant) development of dialects.
Simple conceptual model of semantics.
Can go too far! E.g., Basic, LISP syntax.
"Everything should be as simple as possible, but not simpler" Einstein
Similar syntax => similar semantics.
Bad example: subscript vs fcn def in FORTRAN.
Good example: Instance vble vs parameterless function in Eiffel
Easy to express programs. E.g. support for abstraction.
Success depends on appl.
few basic features - free from interactions. No special restrictions.
Ex. of probs w/ Pascal: Fcn can only return simple type, constants only
defined for built-in basic types, enumerated types cannot be read or written,
etc.
Algol 68 carries to extremes, everything has value.
Smalltalk, Eiffel, other pure object-oriented languages do it well.
Formal grammar, formal semantics helpful but also need well-written manual.
Original presentation usually too vague. Refined.
ALGOL 68 problem w/ redefining terms.
Hoare considered more important than writeability
self-documenting,
commenting conventions: line vs stream oriented.
descriptive identifier names,
blocking of compound statements - if, fi versus begin, end
two-dimensional syntax, syntax directed editors.
COBOL not easier to read.
APL - write-only.
Syntactic and logical (semantic) errors discouraged & easily discovered.
Related to writeability, readability, and modifiability.
Begin-end probs.
problems: Ada out params, Pascal variant records, side-effects.
Diagnostic vs. optimizing compilers?
Practical ConsiderationsPractical Considerations in language choice
"A language that is simple to parse for the compiler is also simple to parse
for the human programmer, and that can only be an asset." Wirth
So people will use it.
hard to achieve completely.
Hoare discusses difference between designing a programming language and
programming language features.
Work on 1 at a time - in familiar context.
Make sure solves problem, without causing new ones.
Show simply and efficiently implemented.
Carefully specify semantics
Use in lots of examples
Know lots of alternatives.
Watch for inconsistencies, interactions.
(Knuth article on remaining problems in Algol 60: interactions major theme,
e.g. side effects and order of evaluation, unexpected exit from control
structure, aliasing - 2 diff. ways of referring to vble, integers also
labels)
Be especially wary of new features
Be ready to make modifications to solve minor problems.
Know intended applications, allowable size and complexity.
Implement on several machines, write manuals and texts
Be prepared to sell it to customers
Don't include untried ideas - consolidation, not innovation.
Make design group as small as possible.
Don't be afraid to revise - once distributed, too hard to change.
Simplicity is really the key - avoid complexity. Too many "solutions" make
language hard to understand.
(See also Hoare, "The emperor's old clothes", CACM, Feb., 1981, pp. 75-83.)
Base programming language on:
- a minimum number of independent concepts combined in a uniform manner.
- a comprehensive definition mechanism to provide the breadth.
- a small core language on which the extensions are based.
- a syntax chosen for its readability.
Most dangerous approach to problems: add new features
Trap PL/I, Ada, and now C++ fell into.
- Abstraction: Avoid requiring something to be stated more than
once; factor out the recurring pattern.
- Automation: Automate mechanical, tedious, or error-prone
activities. (Provide higher level features - e.g. DO loop)
- Defense in Depth: If an error gets through one line of defense,
then it should be caught by the next line of defense. (e.g. if incorrect but
syntactically ok, then should fail type-checking - DO, varieties of GOTO in
FORTRAN)
- Information Hiding: Modules should be designed so that: (1)
The user has all the information needed to use the module correctly, and
nothing more. (2) The implementor has all the information needed to implement
the module correctly, and nothing more.
- Labeling: We should not require the user to know the absolute
position of an item in a list. Instead, we should associate labels with any
position that must be referenced elsewhere. (E.g., labelled case as opposed to
unlabelled)
- Localized Cost: A user should only pay for what he uses; avoid
distributed costs. (Don't build in so much generality that simple things
expensive, e.g ALGOL DO, default param's)
- Manifest Interface: All interfaces must be apparent (manifest)
in the syntax. (Clear how to use, no side-effects)
- Orthogonality: Independent functions should be controlled by
independent mechanisms. (Avoid dependencies -e.g. logic and control).
- Portability: Avoid features or facilities that are dependent on
a particular machine or a small class of machines.
- Preservation of Information: The language should allow the
representation of information that the user knows and that the compiler will
need. (E.g. DO loops, subrange types - make it easier to optimize.)
- Regularity: Regular rules, without exceptions, are easier to
learn, use, describe, and implement.
- Security: No program that violates the definition of the
language, or its own intended structure, should escape detection.
- Simplicity: A language should be as simple as possible. There
should be a minimum number of concepts with simple rules for their combination.
- Structure: The static structure of a program should correspond
in a simple way with the dynamic structure of the corresponding computations.
- Syntactic Consistency: Things which look similar should be
similar and things which look different should be different.
- Zero-One-Infinity: The only reasonable numbers in programming
language design are zero, one, and infinity. (Avoid special cases, E.g.
compound commands in Pascal.)
Originally survey of programming languages: COBOL, FORTRAN, PL/I, LISP, APL,
SNOBOL, etc. (languages for jobs course!).
Get better understanding of principle features of programming languages.
Explore design space of programming languages.
Introduce different ways of thinking about programming reflected by different
programming language paradigms.
What have we done?
- Syntax (formal) and semantics (informal and formal) of common
programming language concepts.
Structure of compilers / interpreters. Importance of binding time.
Variables: static vs. dynamic scoping, lifetime of variables, l-values vs.
r-values.
- Run-time structure of programming languages. Allocation of storage at
run-time. Parameter passing mechanisms. Storage reclamation (explicit - under
programmer control, automatic - garbage collection and reference counting).
- Types in programming languages. Available types and their
representation. Type structures in important representative languages.
- Issues in type-checking: Static vs. dynamic type-checking. Type
compatibility (structural vs. name equivalence). Holes in type systems (e.g.
variant records). Problems with pointers.
- Abstract data types and representation in programming languages.
- Expressions: Order of evaluation (including short-circuit evaluation),
functions, and side-effects
- Control structures (including exception handling).
- Polymorphism - implicit and explicit.
- Programming in the large: Support from languages (information hiding,
encapsulation, separate but not independent compilation, explicit importing and
exporting of environments.) Top-down vs. object-based design.
- Programming language paradigms:
- Imperative: Assignment statements (incl. order of evaluation,
side-effects, and aliasing) and control structures. Iterators. Procedures,
coroutines.
- Functional: Expanded expression constructs. Pattern matching and type
inference. Higher-order functions. Lazy vs. eager languages. Recursively
defined types. Implementation issues (efficiency and possibility of
implementation on highly-parallel computers). Program verification. ML as an
example.
- Logic: Basis in mathematical logic - extract program from proof.
Relational programming (and reversability of computations). Computation as
backtracking + unification. Relation to resolution theorem proving.
Separation of logic and control (NOT!). Importance of ordering of clauses.
Use of cut. Closed-world assumption and negation. Limitations of Prolog as an
implementation of logic programming (lack of soundness and completeness).
- Object-oriented: Origins in object-based languages supporting ADT's.
Key features: objects and classes, message passing & dynamic method
invocation, subclasses and inheritance, subtyping, etc. Support for
abstractions and information-hiding. Object-oriented view of algorithms.
Support for incremental modification through inheritance and subclasses.
Difference between subtyping and inheritance. Type-checking problems in
popular languages. Complications in semantics of inheritance. Loss of
locality in inheritance.
- Concurrency: Semaphores, monitors, and message passing.
- Semantics: Operational, Axiomatic, and denotational semantics.
- Evolution of programming languages. Problems which led to introduction
of new constructs.
- Criteria for language design: Writeability, readability,
reliability, efficiency considerations, portability. How to design features
and languages. How to choose a language.
Graduate level course would be more formal and have less emphasis on learning
individual languages. (Either operational or denotational semantics.)
Hope have better understanding of options open to programmer. How language can
support programmer (as well as awareness of traps). Different paradigms
represent different ways of thinking about programming (don't expect to have
become expert programmers in languages taught).