Table Of ContentTexts in Computer Science
Torben Ægidius Mogensen
Programming
Language
Design and
Implementation
Texts in Computer Science
Series Editors
David Gries, Department of Computer Science, Cornell University, Ithaca, NY,
USA
OritHazzan ,FacultyofEducationinTechnologyandScience,Technion—Israel
Institute of Technology, Haifa, Israel
Titles in this series now included in the Thomson Reuters Book Citation Index!
‘TextsinComputerScience’(TCS)delivershigh-qualityinstructionalcontentfor
undergraduates and graduates in all areas of computing and information science,
with a strong emphasis on core foundational and theoretical material but inclusive
of some prominent applications-related content. TCS books should be reasonably
self-containedandaimtoprovidestudentswithmodernandclearaccountsoftopics
ranging across the computing curriculum. As a result, the books are ideal for
semestercoursesorforindividualself-studyincaseswherepeopleneedtoexpand
their knowledge. All texts are authored by established experts in their fields,
reviewed internally and by the series editors, and provide numerous examples,
problems, and other pedagogical tools; many contain fully worked solutions.
The TCS series is comprised of high-quality, self-contained books that have
broad and comprehensive coverage and are generally in hardback format and
sometimes contain color. For undergraduate textbooks that are likely to be more
brief and modular in their approach, require only black and white, and are under
275pages,SpringerofferstheflexiblydesignedUndergraduateTopicsinComputer
Science series, to which we refer potential authors.
Torben Ægidius Mogensen
Programming Language
Design and
Implementation
123
Torben ÆgidiusMogensen
Department ofComputer Science
University of Copenhagen
Copenhagen, Denmark
ISSN 1868-0941 ISSN 1868-095X (electronic)
Textsin Computer Science
ISBN978-3-031-11805-0 ISBN978-3-031-11806-7 (eBook)
https://doi.org/10.1007/978-3-031-11806-7
©TheEditor(s)(ifapplicable)andTheAuthor(s),underexclusivelicensetoSpringerNature
SwitzerlandAG2022
Thisworkissubjecttocopyright.AllrightsaresolelyandexclusivelylicensedbythePublisher,whether
thewholeorpartofthematerialisconcerned,specificallytherightsoftranslation,reprinting,reuseof
illustrations, recitation, broadcasting, reproduction on microfilms or in any other physical way, and
transmissionorinformationstorageandretrieval,electronicadaptation,computersoftware,orbysimilar
ordissimilarmethodologynowknownorhereafterdeveloped.
The use of general descriptive names, registered names, trademarks, service marks, etc. in this
publicationdoesnotimply,evenintheabsenceofaspecificstatement,thatsuchnamesareexemptfrom
therelevantprotectivelawsandregulationsandthereforefreeforgeneraluse.
The publisher, the authors, and the editorsare safeto assume that the adviceand informationin this
book are believed to be true and accurate at the date of publication. Neither the publisher nor the
authors or the editors give a warranty, expressed or implied, with respect to the material contained
hereinorforanyerrorsoromissionsthatmayhavebeenmade.Thepublisherremainsneutralwithregard
tojurisdictionalclaimsinpublishedmapsandinstitutionalaffiliations.
ThisSpringerimprintispublishedbytheregisteredcompanySpringerNatureSwitzerlandAG
Theregisteredcompanyaddressis:Gewerbestrasse11,6330Cham,Switzerland
Preface
Design is a funny word. Some people think design means
howitlooks.Butofcourse,ifyoudigdeeper,it’sreallyhow
itworks.
SteveJobs
Successfuldesignisnottheachievementofperfectionbutthe
minimizationandaccommodationofimperfection.
HenryPetroski
This book aims to provide the reader with an overview of the design space for
programming languages and how design choices affect implementation.
Itisnotaclassicalcompilersbook,asitassumesthereaderisfamiliarwithbasic
compiler implementation techniques, nor is it a traditional comparative program-
ming languages book, because it does not go into depth about any particular lan-
guage,butinsteadtakeexamplesfromawidevarietyofprogramminglanguagesto
illustrate design concepts.
Thebookisorganisedaroundconcepts.Eachconcepthasachapterthatexplains
the concept, illustrates the concept through examples from past and present (using
bothmainstreamandobscurelanguages),discussionaboutprosandconsofdesign
choices, implementation and, where deemed necessary, a bit offormal theory.
It istheopinionoftheauthor thatadesignerofprogramming languagesshould
not only know what other language designers have done, but also have an opera-
tional understanding of the consequences design choices have on implementation
of these languages. Otherwise, the designer is liable to make design choices that
rendersimplementationexcessivelydifficult,impedesperformanceormakesitvery
hard for the users of the language to predict the behaviour of programs, especially
whenseverallanguagefeaturesareusedincombination.Therefore,thedescription
ofthedesignspaceofvariouslanguagefeaturesincludesdiscussionandsketchesof
implementation.Thesesketchesarenotverydetailed,butacompetentprogrammer
withknowledgeofbasiccompilertechniquesshouldbeabletousethesketchesasa
guide for implementation.
If this book can help just one language designer avoid making design choices
that she or the users of her language later regrets, it is deemed a success.
v
vi Preface
Do We Need New Programming Languages?
In the 1930s, Alonzo Church and Alan Turing independently proposed models for
mechanicalcomputation.Thesemodelsarenowknownasthelambdacalculusand
Turing machines, respectively. Together with the logicians Stephen Kleene and
J. B. Rosser, they later proved that any computation that can be done using the
lambdacalculuscanalsobedoneusingTuringmachines,andviceversa.Giventhat
the two models are radically different, this led Church and Turing to hypothesise
that no model of computation that can be realised by a physical machine can
performcomputationsthatcannotalsobeperformedbylambdacalculusandTuring
machines.Thesemodelsareinthissenseuniversal:Theycanbeusedtomodelany
computation, and if something is proven to not be computable using a Turing
Machine(orthelambdacalculus),thenitcannotbecomputedatallonamechanical
device. This hypothesis is called Church-Turing Thesis. It is not possible to prove
this thesis, as there is no generally accepted formal definition of a mechanical
device, but it is generally accepted to be true, as nobody has come up with a
physicallyrealisablemodelformechanical(orelectronic)computationthatexceeds
the power of Turing machines or lambda calculus. A programming language that
(assuming no upper bound on available memory) can do everything a Turing
machine or the lambda calculus can do is called Turing complete.
Most programming languages are Turing complete, so you can argue that there
is no need for new programming languages, as they will not be able to do some-
thing that cannot already be done. Even so, new languages appear all the time, so
computational power is not the only interesting criterion for programming lan-
guages.Butitcanbeveryhardtofindobjectivecriteriaforwhenanewlanguageis
better than an existing language. Common criteria are:
Program size: Are programs in language A shorter than equivalent programs in
language B?
Speed: Do programs in language A run faster than equivalent programs in
language B?
Ease of programming: Is it easier to write a program in language A than an
equivalent program in language B?
Ease of reasoning about programs: Is it easier to prove correctness of programs in
language A than in language B.
But these criteria all have problems:
Programsize:IfbothAandBareTuringcompletelanguages,andBcanrepresent
the text of programs in A as constants (such as strings) without significant
expansion,itispossibletorewriteanysufficientlylargeprogramwritteninAto
anequivalentprogramwritteninBthatisonlyinsignificantlylarger.Basically,
therewrittenprogramcontainsaninterpreterforAandtherepresentationofthe
original program. So any difference in program size will only affect relatively
small programs.
Preface vii
Speed:Speedofexecutionismoreamatterofhowalanguageisimplementedthan
howitisdesigned.Youcan,atbest,comparethespeedofaparticularprogram
written in language A using a particular implementation of this language to a
specificequivalentprograminaspecificimplementationoflanguageB.Butitis
hard to argue that the two programs represent the fastest way of doing this
computation in their respective language implementations, so this says little
aboutthespeedoftheprogramsthemselves,andevenlessaboutthelanguages.
Ease of programming: This is a highly subjective matter: One programmer can
think that it is much easier to program in language A, while another prefers
language B. Even if you teach non-programmers to program in two different
languages,spendingequaleffortonboth,theirpreferencesmaydependontheir
cultural background, education, or personality, so it is, again, hard so say
something objective about the languages themselves.
Ease of reasoning about programs: For Turing complete programming languages,
provingthatprogramsarecorrectwithrespecttosomespecificationorthatthey
havesomedesirableproperty(suchastermination)isingeneralundecidable,so
you can argue that all such languages are equally difficult to reason about. On
theotherhand,ineverylanguage,youcanprovecorrectnessandterminationfor
some programs, so you can discuss the relative ease of doing so for similar
programs in different languages. But reaching definitive conclusions from such
discussions is difficult, because the requirement that the programs be similar
mayrequireoneorbothprogramstobecodedinawaythatisnottypicalforthe
languages in question, so you can easily end up arguing about program style
rather than languages.
This does not mean that it is impossible to compare programming languages—
oneshouldjustavoidverygeneralstatementsliketheabove,andoneshouldmake
reservationsclear.Butitisperfectlypossibletoarguethatforaspecifictypeofuser
(programmer), for a specific type of problem, for specific implementations, one
language is better suited than another.
This also means that a new programming language typically is designed for a
specifictype ofuser (programmer), for aspecifictypeofproblem, orfor aspecific
implementation method or machine.
Weak Languages
Many of the observations above rely on languages being Turing complete. If a
language is not Turing complete, you can perfectly well and precisely argue about
computationalpower,programsizeandexecutionspeed(onanon-Turingcomplete
machine).Butwhywouldyouwanttousealanguagethatprovablycannotbeused
for any sort of computation?
Turing completeness may give the highest possible power of computation, but
this power itself has a prize: It can be very hard or impossibleto decide properties
about programs written in Turing complete languages:
viii Preface
(cid:129) Itmaybeimpossibletoprovethataprogramiscorrectwithrespecttoaformal
specification.Someprogramscanbeprovencorrect,butthereareprogramsthat
can neither be proven correct nor incorrect.
(cid:129) Itmaybeimpossibletogiveboundsoncomputationtimeorresourceuse—even
if you just want to know if the bounds are finite or not. Again, it is possible to
prove bounds on some programs, but some programs will escape proof.
Itispossibletodesignprogramminglanguageswheresuchprooforboundscan
always be found, but this will be at the cost of Turing completeness. Many
domain-specificlanguageswillbedeliberatelydesignedthiswaytoensurespecific
properties. While these languages can be useless outside the problem domain for
which they are designed, they can be very useful for solving problems inside this
domain.
General Design Principles
The remainder of the book will investigate design choices for different aspects of
programming languages, but there are some cross-cutting guidelines that apply to
the design process as a whole. The following guidelines are not hard laws, but
something a designer should at least think about.
1. Thereisnosingleperfectlanguagedesignforanygivenpurpose.Thisdoesnot
mean that all designs are equally good—there are plenty of examples of bad
language design.
2. Fewdesignchoicesaregoodorbadinisolation,butonedesignchoicemayfita
given purpose better than others. And some sets of design choices can benefit
each other while other sets can interact badly.
3. Make everything as simple as possible, but no simpler.1 Simplicity is a good
design principle, but one should not over-simplify, as that can impact
practicality.
4. If a language is difficult to describe precisely, it is likely difficult to understand
and use. So make sure syntax and semantics have clear (possibly formal)
descriptions.
5. When you design a language or language feature, you should have at least a
rough idea of how this can be implemented. This understanding need not be
presentwhenalanguageorfeatureisinvestigated(indeed,theinvestigationmay
include research for implementation techniques), but it should be before a final
design decision is made.
6. Excepting very specialised (domain-specific) languages, a programming lan-
guage is not very useful unless it is supported by a comprehensive library—if
youhavetowriteeverythingfromscratch,allbutthemosttrivialprogramswill
1ThissayingisusuallyattributedtoAlbertEinsten.
Preface ix
be major efforts. So, unless you have resources to write a substantial library
from scratch, you should enable the use of libraries written in or for other
programming languages.
To the Reader
Thebookhasbeendesignedtobeusedasatextbookinanadvancedundergraduate
or introductory graduate course in computer science and related fields, but it can
also be used by professionals who want to design and implement their own pro-
gramminglanguages,regardlessofwhethertheseareintendedforpersonaluseonly
or they are hoped to become used by a large number of people.
Thebookassumesthatthereaderisfamiliarwithbasiccompilertechniquessuch
as parsing and code generation at a level corresponding to an undergraduate
introductory compilers course. It also assumes the reader has experience with
programminginatleastacoupleofsignificantlydifferentprogramminglanguages.
In particular,the reader should have at least a bit experience with polymorphically
typed functional languages with pattern matching (such as Standard ML, OCaml,
F# or Haskell) imperative languages (primarily C), and object-oriented languages
(such as Java or C#). If you haven’t already, you can try these languages (and
others) out when they are mentioned in the book. There are plenty of online
tutorials you can use for this.
Like in most textbooks, each chapter concludes with a number of exercises.
These are primarily intended to help the reader get a better understanding of the
concepts in the chapter. For this reason, many sections in a chapter will conclude
with a few suggestions of exercises that the reader is encouraged to try solving
before continuing to the next section.
Every chapter also includes a list of suggested further reading that goes deeper
into the subjects covered in the chapter.
Copenhagen, Denmark Torben Ægidius Mogensen