tctc a 1 (cforall) user manual 2 version 1.0 3 “describe not prescribe” c a team andrew beach,...

101
DRAFT C A (Cforall) User Manual 1 Version 1.0 2 “describe not prescribe” 3 C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves, Aaron Moss, Rob Schluntz 4 March 5, 2020 5 © 2016 C A Project 6 7 This work is licensed under the Creative Commons Attribution 4.0 International License. To view a copy of 8 this license, visit http://creativecommons.org/licenses/by/4.0. 9

Upload: others

Post on 27-May-2020

13 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

DRA

FTC

A

(Cforall) User Manual1

Version 1.02

“describe not prescribe”3

C

A

TeamAndrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle,

Glen Ditchfield, Rodolfo G. Esteves, Aaron Moss, Rob Schluntz

4

March 5, 20205

© 2016 C

A

Project6

7

This work is licensed under the Creative Commons Attribution 4.0 International License. To view a copy of8

this license, visit http://creativecommons.org/licenses/by/4.0.9

Page 2: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

Contents1

1 Introduction 12

1.1 Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2 Why fix C? 24

3 History 35

4 Interoperability 36

5 Compiling a CFA Program 47

6 Backquote Identifiers 58

7 Constant Underscores 69

8 Exponentiation Operator 610

9 Control Structures 711

9.1 if/while Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 712

9.2 case Clause . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 713

9.3 switch Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 814

9.4 Non-terminating and Labelled fallthrough . . . . . . . . . . . . . . . . . . . . . . . . . . . 1215

9.5 Loop Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1216

9.6 Labelled continue / break Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1317

10 with Statement 1318

11 Exception Handling 1819

11.1 Exception Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1820

12 Alternative Declarations 1921

13 Pointer / Reference 2022

13.1 Initialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2323

13.2 Address-of Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2524

13.3 Conversions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2625

14 Routine Definition 2626

14.1 Named Return Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2727

14.2 Routine Prototype . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2828

15 Routine Pointers 2929

16 Named and Default Arguments 2930

17 Unnamed Structure Fields 3231

ii

Page 3: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

CONTENTS iii

18 Nesting 321

18.1 Type Nesting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322

18.2 Routine Nesting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323

19 Tuple 334

19.1 Multiple-Return-Value Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345

19.2 Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356

19.3 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357

19.4 Indexing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368

19.5 Flattening and Structuring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369

19.6 Assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3710

19.7 Construction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3911

19.8 Member-Access Expression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3912

19.9 Casting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4013

19.10Polymorphism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4114

19.10.1 Assertion Inference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4215

20 Tuples 4316

20.1 Tuple Coercions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4417

20.2 Mass Assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4518

20.3 Multiple Assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4619

20.4 Cascade Assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4620

21 Stream I/O Library 4721

21.1 Implicit Separator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4822

21.2 Separation Manipulators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4823

21.3 Newline Manipulators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5024

21.4 Output Value Manipulators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5025

21.5 Input Value Manipulators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5326

22 Types 5427

22.1 Type Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5428

22.2 Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5529

23 Constructors and Destructors 5630

24 Overloading 5631

24.1 Overloaded Constant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5632

24.2 Variable Overloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5833

24.3 Function Overloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5834

24.4 Operator Overloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5935

25 Auto Type-Inferencing 6036

26 Concurrency 6137

26.1 Coroutine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6138

26.2 Monitors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6139

26.3 Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6140

Page 4: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

iv CONTENTS

27 Language Comparisons 611

27.1 C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 622

27.2 Go . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 653

27.3 Rust . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 654

27.4 D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 655

A Syntax Ambiguities 656

B C Incompatibles 667

C C

A

Keywords 698

D Standard Headers 709

E Standard Library 7010

E.1 Storage Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7011

E.2 String to Value Conversion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7212

E.3 Search / Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7313

E.4 Absolute Value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7314

E.5 Random Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7415

E.6 Algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7416

F Math Library 7417

F.1 General . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7418

F.2 Exponential . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7519

F.3 Logarithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7520

F.4 Trigonometric . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7621

F.5 Hyperbolic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7722

F.6 Error / Gamma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7823

F.7 Nearest Integer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7924

F.8 Manipulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8025

G Time Keeping 8026

G.1 Duration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8027

G.2 timeval . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8228

G.3 timespec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8229

G.4 itimerval . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8230

G.5 Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8231

H Clock 8332

H.1 C time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8333

H.2 Clock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8434

I Multi-precision Integers 8435

J Rational Numbers 8736

Index 9137

Page 5: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

1 Introduction1

C

A1 is a modern general-purpose programming-language, designed as an evolutionary step forward for the2

C programming language. The syntax of C

A

builds from C and should look immediately familiar to C/C++3

programmers. C

A

adds many modern programming-language features that directly lead to increased safety4

and productivity, while maintaining interoperability with existing C programs and achieving similar perfor-5

mance. Like C, C

A

is a statically typed, procedural (non-object-oriented) language with a low-overhead6

runtime, meaning there is no global garbage-collection, but regional garbage-collection is possible. The7

primary new features include polymorphic routines and types, exceptions, concurrency, and modules.8

One of the main design philosophies of C

A

is to “describe not prescribe”, which means C

A

tries to9

provide a pathway from low-level C programming to high-level C

A

programming, but it does not force10

programmers to “do the right thing”. Programmers can cautiously add C

A

extensions to their C programs in11

any order and at any time to incrementally move towards safer, higher-level programming. A programmer is12

always free to reach back to C from C

A

, for any reason, and in many cases, new C

A

features can be locally13

switched back to there C counterpart. There is no notion or requirement for rewriting a legacy C program in14

C

A

; instead, a programmer evolves a legacy program into C

A

by incrementally incorporating C

A

features.15

As well, new programs can be written in C

A

using a combination of C and C

A

features.16

C++ [28] had a similar goal 30 years ago, allowing object-oriented programming to be incrementally17

added to C. However, C++ currently has the disadvantages of a strong object-oriented bias, multiple legacy18

design-choices that cannot be updated, and active divergence of the language model from C, requiring19

significant effort and training to incrementally add C++ to a C-based project. In contrast, C

A

has 30 years of20

hindsight and a clean starting point.21

Like C++, there may be both an old and new ways to achieve the same effect. For example, the following22

programs compare the C, C

A

, and C++ I/O mechanisms, where the programs output the same result.23

C C

A

C++

#include <stdio.h>

int main( void ) {int x = 0, y = 1, z = 2;

printf( "%d %d %d\n", x, y, z );

}

#include <fstream>

int main( void ) {int x = 0, y = 1, z = 2;

sout | x | y | z;

}

#include <iostream>using namespace std;

int main() {int x = 0, y = 1, z = 2;

cout<<x<<" "<<y<<" "<<z<<endl;

}

24

While the C

A

I/O looks similar to the C++ output style, there are important differences, such as automatic25

spacing between variables as in Python (see Section ??, p. ??).26

1.1 Background27

This document is a programmer reference-manual for the C

A

programming language. The manual covers the28

core features of the language and runtime-system, with simple examples illustrating syntax and semantics29

of features. The manual does not teach programming, i.e., how to combine the new constructs to build30

complex programs. The reader must have an intermediate knowledge of control flow, data structures, and31

concurrency issues to understand the ideas presented, as well as some experience programming in C/C++.32

Implementers should refer to the C

A

Programming Language Specification for details about the language33

syntax and semantics. Changes to the syntax and additional features are expected to be included in later34

revisions.35

1Pronounced “C-for-all”, and written C

A

, CFA, or Cforall.

1

Page 6: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

2 2 Why fix C?

2 Why fix C?1

The C programming language is a foundational technology for modern computing with millions of lines of2

code implementing everything from hobby projects to commercial operating-systems. This installation base3

and the programmers producing it represent a massive software-engineering investment spanning decades4

and likely to continue for decades more. Even with all its problems, C continues to be popular because it5

allows writing software at virtually any level in a computer system without restriction. For system program-6

ming, where direct access to hardware, storage management, and real-time issues are a requirement, C is7

usually the only language of choice. The TIOBE index [30] for February 2020 ranks the top six most8

popular programming languages as Java 17.4%, C 16.8%, Python 9.3%, C++ 6.2%, C♯ 5.9%, Visual Basic9

5.9% = 61.5%, where the next 50 languages are less than 2% each, with a long tail. The top 4 rankings over10

the past 35 years are:11

2020 2015 2010 2005 2000 1995 1990 1985

Java 1 2 1 2 3 - - -

C 2 1 2 1 1 2 1 1

Python 3 7 6 6 22 21 - -

C++ 4 4 4 3 2 1 2 12

12

Hence, C is still an extremely important programming language, with double the usage of C++; in many13

cases, C++ is often used solely as a better C. Love it or hate it, C has been an important and influential part14

of computer science for 40 years and its appeal is not diminishing. Nevertheless, C has many problems and15

omissions that make it an unacceptable programming language for modern needs.16

As stated, the goal of the C

A

project is to engineer modern language-features into C in an evolutionary17

rather than revolutionary way. C++ [7, 14] is an example of a similar project; however, it largely extended18

the C language, and did not address most of C’s existing problems.2 Fortran [16], Ada [1], and Cobol [8] are19

examples of programming languages that took an evolutionary approach, where modern language-features20

(e.g., objects, concurrency) are added and problems fixed within the framework of the existing language.21

Java [20], Go [21], Rust [27] and D [3] are examples of the revolutionary approach for modernizing C/C++,22

resulting in a new language rather than an extension of the descendent. These languages have different23

syntax and semantics from C, do not interoperate directly with C, and are not systems languages because24

of restrictive memory-management or garbage collection. As a result, there is a significant learning curve25

to move to these languages, and C legacy-code must be rewritten. These costs can be prohibitive for many26

companies with a large software-base in C/C++, and a significant number of programmers require retraining27

in the new programming language.28

The result of this project is a language that is largely backwards compatible with C11 [6], but fixes many29

of the well known C problems while adding modern language-features. To achieve these goals required a30

significant engineering exercise, where we had to “think inside the existing C box”. Without these signifi-31

cant extension to C, it is unable to cope with the needs of modern programming problems and programmers;32

as a result, it will fade into disuse. Considering the large body of existing C code and programmers, there33

is significant impetus to ensure C is transformed into a modern programming language. While C11 made34

a few simple extensions to the language, nothing was added to address existing problems in the language35

or to augment the language with modern language-features. While some may argue that modern language-36

features may make C complex and inefficient, it is clear a language without modern capabilities is insuffi-37

cient for the advanced programming problems existing today.38

2Two important existing problems addressed were changing the type of character literals from int to char and enumerator from int

to the type of its enumerators.

Page 7: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

3 History 3

3 History1

The C

A

project started with Dave Till’s K-W C [5, 29], which extended C with new declaration syntax,2

multiple return values from routines, and advanced assignment capabilities using the notion of tuples.3

(See [31] for similar work in C++.) The first C

A

implementation of these extensions was by Rodolfo4

Esteves [15].5

The signature feature of C

A

is overloadable parametric-polymorphic functions [9, 10, 13] with functions6

generalized using a forall clause (giving the language its name):7

forall( otype T ) T identity( T val ) { return val; }8

int forty two = identity( 42 ); // T is bound to int, forty two == 429

C

A

’s polymorphism was originally formalized by Glen Ditchfield [11], and first implemented by Richard10

Bilson [2]. However, at that time, there was little interesting in extending C, so work did not continue. As the11

saying goes, “What goes around, comes around.”, and there is now renewed interest in the C programming12

language because of legacy code-bases, so the C

A

project has been restarted.13

4 Interoperability14

C

A

is designed to integrate directly with existing C programs and libraries. The most important feature of15

interoperability is using the same calling conventions, so there is no complex interface or overhead to call16

existing C routines. This feature allows C

A

programmers to take advantage of the existing panoply of C17

libraries to access thousands of external software features. Language developers often state that adequate18

library support takes more work than designing and implementing the language itself. Fortunately, C

A

,19

like C++, starts with immediate access to all exiting C libraries, and in many cases, can easily wrap library20

routines with simpler and safer interfaces, at very low cost. Hence, C

A

begins by leveraging the large21

repository of C libraries, and than allows programmers to incrementally augment their C programs with22

modern backward-compatible features.23

However, it is necessary to differentiate between C and C

A

code because of name overloading, as for24

C++. For example, the C math-library provides the following routines for computing the absolute value of25

the basic types: abs, labs, llabs, fabs, fabsf, fabsl, cabsf, cabs, and cabsl. Whereas, C

A

wraps each of these26

routines into ones with the overloaded name abs:27

char abs( char );28

extern "C" { int abs( int ); } // use default C routine for int29

long int abs( long int );30

long long int abs( long long int );31

float abs( float );32

double abs( double );33

long double abs( long double );34

float Complex abs( float Complex );35

double Complex abs( double Complex );36

long double Complex abs( long double Complex );37

The problem is the name clash between the library routine abs and the C

A

names abs. Hence, names38

appearing in an extern "C" block have C linkage. Then overloading polymorphism uses a mechanism39

called name mangling to create unique names that are different from C names, which are not mangled.40

Hence, there is the same need, as in C++, to know if a name is a C or C

A

name, so it can be correctly formed.41

There is no way around this problem, other than C’s approach of creating unique names for each pairing of42

operation and types.43

This example strongly illustrates a core idea in C

A

: the power of a name. The name “abs” evokes44

the notion of absolute value, and many mathematical types provide the notion of absolute value. Hence,45

Page 8: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

4 5 Compiling a CFA Program

knowing the name abs is sufficient to apply it to any type where it is applicable. The time savings and safety1

of using one name uniformly versus N unique names cannot be underestimated.2

5 Compiling a C

A

Program3

The command cfa is used to compile a C

A

program and is based on the GNU gcc command, e.g.:4

cfa [ gcc options ] [ C/C

A

source files ] [ assembler/loader files ]5

C

A

programs having the following gcc flags turned on:6

std=gnu11 The 2011 C standard plus GNU extensions.7

fgnu89 inline Use the traditional GNU semantics for inline routines in C11 mode, which allows inline8

routines in header files.9

The following new C

A

options are available:10

CFA Only the C preprocessor and the C

A

translator steps are performed and the transformed program is11

written to standard output, which makes it possible to examine the code generated by the C

A

translator.12

The generated code starts with the standard C

A

prelude.13

debug The program is linked with the debugging version of the runtime system. The debug version14

performs runtime checks to help during the debugging phase of a C

A

program, but can substantially15

slow program execution. The runtime checks should only be removed after the program is completely16

debugged. This option is the default.17

nodebug The program is linked with the non-debugging version of the runtime system, so the execution18

of the program is faster. However, no runtime checks or asserts are performed so errors usually result19

in abnormal program behaviour or termination.20

help Information about the set of C

A

compilation flags is printed.21

nohelp Information about the set of C

A

compilation flags is not printed. This option is the default.22

quiet The C

A

compilation message is not printed at the beginning of a compilation.23

noquiet The C

A

compilation message is printed at the beginning of a compilation. This option is the24

default.25

The following preprocessor variables are available:26

CFA MAJOR is available during preprocessing and its value is the major version number of C

A

.327

CFA MINOR is available during preprocessing and its value is the minor version number of C

A

.28

CFA PATCH is available during preprocessing and its value is the patch level number of C

A

.29

CFA , CFORALL , and cforall are always available during preprocessing and have no value.30

These preprocessor variables allow conditional compilation of programs that must work differently in these31

situations. For example, to toggle between C and C

A

extensions, use the following:32

#ifndef CFORALL33

#include <stdio.h> // C header file34

#else35

#include <fstream> // C

A

header file36

#endif37

3 The C preprocessor allows only integer values in a preprocessor variable so a value like “1.0.0.0 ” is not allowed. Hence, the need

to have three variables for the major, minor and patch version number.

Page 9: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

6 Backquote Identifiers 5

which conditionally includes the correct header file, if the program is compiled using gcc or cfa.1

The C

A

translator has multiple steps. The following flags control how the tranlator works, the stages run,2

and printing within a stage. The majority of these flags are used by C

A

developers, but some are occasionally3

useful to programmers.4

h, help print help message5

l, libcfa generate libcfa.c6

L, linemarks generate line marks7

m, no main do not replace main8

N, no linemarks do not generate line marks9

n, no prelude do not read prelude10

p, prototypes generate prototypes for prelude functions11

P, print one of:12

altexpr alternatives for expressions13

ascodegen as codegen rather than AST14

ast AST after parsing15

astdecl AST after declaration validation pass16

asterr AST on error17

astexpr AST after expression analysis18

astgen AST after instantiate generics19

box before box step20

ctordtor after ctor/dtor are replaced21

codegen before code generation22

declstats code property statistics23

parse yacc (parsing) debug information24

pretty prettyprint for ascodegen flag25

resolver before resolver step26

rproto resolver-proto instance27

rsteps resolver steps28

symevt symbol table events29

tree parse tree30

tuple after tuple expansion31

prelude dir <directory> prelude directory for debug/nodebug32

S, statistics <option-list> enable profiling information:33

counters,heap,time,all,none34

t, tree build in tree35

6 Backquote Identifiers36

C

A

introduces several new keywords (see Section C, p. 69) that can clash with existing C variable-names37

in legacy code. Keyword clashes are accommodated by syntactic transformations using the C

A

backquote38

escape-mechanism:39

int ‘‘otype = 3; // make keyword an identifier40

double ‘‘forall = 3.5;41

Existing C programs with keyword clashes can be converted by enclosing keyword identifiers in back-42

quotes, and eventually the identifier name can be changed to a non-keyword name. Figure 1 shows how43

clashes in existing C header-files (see Section D, p. 70) can be handled using preprocessor interposition:44

#include next and I filename. Several common C header-files with keyword clashes are fixed in the stan-45

Page 10: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

6 8 Exponentiation Operator

// include file uses the CFA keyword "with".

#if ! defined( with ) // nesting ?

#define with ‘‘with // make keyword an identifier#define CFA BFD H

#endif

#include next <bfdlink.h> // must have internal check for multiple expansion

#if defined( with ) && defined( CFA BFD H ) // reset only if set

#undef with

#undef CFA BFD H

#endif

Figure 1: Header-File Interposition

dard C

A

header-library, so there is a seamless programming-experience.1

7 Constant Underscores2

Numeric constants are extended to allow underscores, e.g.:3

2 147 483 648; // decimal constant4

56 ul; // decimal unsigned long constant5

0 377; // octal constant6

0x ff ff; // hexadecimal constant7

0x ef3d aa5c; // hexadecimal constant8

3.141 592 654; // floating constant9

10 e +1 00; // floating constant10

0x ff ff p 3; // hexadecimal floating11

0x 1.ffff ffff p 128 l; // hexadecimal floating long constant12

L "\x ff ee"; // wide character constant13

The rules for placement of underscores are:14

1. A sequence of underscores is disallowed, e.g., 12 34 is invalid.15

2. Underscores may only appear within a sequence of digits (regardless of the digit radix). In other16

words, an underscore cannot start or end a sequence of digits, e.g., 1, 1 and 1 are invalid (actually,17

the 1st and 3rd examples are identifier names).18

3. A numeric prefix may end with an underscore; a numeric infix may begin and/or end with an under-19

score; a numeric suffix may begin with an underscore. For example, the octal 0 or hexadecimal 0x20

prefix may end with an underscore 0 377 or 0x ff; the exponent infix E may start or end with an21

underscore 1.0 E10, 1.0E 10 or 1.0 E 10; the type suffixes U, L, etc. may start with an underscore22

1 U, 1 ll or 1.0E10 f.23

It is significantly easier to read and enter long constants when they are broken up into smaller groupings24

(many cultures use comma and/or period among digits for the same purpose). This extension is backwards25

compatible, matches with the use of underscore in variable names, and appears in Ada and Java 8.26

8 Exponentiation Operator27

C, C++, and Java (and many other programming languages) have no exponentiation operator, i.e., xy, and28

instead use a routine, like pow(x,y), to perform the exponentiation operation. C

A

extends the basic operators29

with the exponentiation operator ?\? and ?\=?, as in, x \ y and x \= y, which means xy and x← xy. The priority30

Page 11: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

9 Control Structures 7

of the exponentiation operator is between the cast and multiplicative operators, so that w * (int)x \ (int)y * z1

is parenthesized as ((w * (((int)x) \ ((int)y))) * z).2

There are exponentiation operators for integral and floating types, including the builtin complex types.3

Integral exponentiation is performed with repeated multiplication4 (or shifting if the exponent is 2). Over-4

flow for a large exponent or negative exponent returns zero. Floating exponentiation is performed using5

logarithms, so the exponent cannot be negative.6

sout | 1 \ 0 | 1 \ 1 | 2 \ 8 | 4 \ 3 | 5 \ 3 | 5 \ 32 | 5L \ 32 | 5L \ 64 | 4 \ 3 | 4.0 \ 3 | 4.0 \ 2.17

| (1.0f+2.0fi) \ (3.0f+2.0fi);8

1 1 256 64 125 0 3273344365508751233 0 0 0.015625 18.3791736799526 0.264715 1.1922i9

Note, 5 \ 32 and 5L \ 64 overflow, and 4 \ 3 is a fraction but stored in an integer so all three computations10

generate an integral zero. Parenthesis are necessary for complex constants or the expression is parsed as11

1.0f+(2.0fi \ 3.0f)+2.0fi. The exponentiation operator is available for all the basic types, but for user-defined12

types, only the integral-computation version is available.13

forall( otype OT | { void ?{}( OT & this, one t ); OT ?*?( OT, OT ); } )14

OT ?\?( OT ep, unsigned int y );15

forall( otype OT | { void ?{}( OT & this, one t ); OT ?*?( OT, OT ); } )16

OT ?\?( OT ep, unsigned long int y );17

The user type T must define multiplication, one (1), and *.18

9 Control Structures19

C

A

identifies inconsistent, problematic, and missing control structures in C, and extends, modifies, and adds20

control structures to increase functionality and safety.21

9.1 if/while Statement22

The if/while expression allows declarations, similar to for declaration expression. (Does not make sense for23

do-while.)24

if ( int x = f() ) ... // x != 025

if ( int x = f(), y = g() ) ... // x != 0 && y != 026

if ( int x = f(), y = g(); x < y ) ... // relational expression27

if ( struct S { int i; } x = { f() }; x.i < 4 ) // relational expression28

29

while ( int x = f() ) ... // x != 030

while ( int x = f(), y = g() ) ... // x != 0 && y != 031

while ( int x = f(), y = g(); x < y ) ... // relational expression32

while ( struct S { int i; } x = { f() }; x.i < 4 ) ... // relational expression33

Unless a relational expression is specified, each variable is compared not equal to 0, which is the standard34

semantics for the if/while expression, and the results are combined using the logical && operator.5 The scope35

of the declaration(s) is local to the @if@ statement but exist within both the “then” and “else” clauses.36

9.2 case Clause37

C restricts the case clause of a switch statement to a single value. For multiple case clauses associated with38

the same statement, it is necessary to have multiple case clauses rather than multiple values. Requiring a39

4The multiplication computation is O(logy).5C++ only provides a single declaration always compared not equal to 0.

Page 12: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

8 9.3 switch Statement

case clause for each value does not seem to be in the spirit of brevity normally associated with C. Therefore,1

the case clause is extended with a list of values, as in:2

C

A

C

switch ( i ) {case 1, 3, 5:

...case 2, 4, 6:

...

}

switch ( i ) {case 1: case 3 : case 5:

...case 2: case 4 : case 6:

...

}

// odd values

// even values

3

In addition, subranges are allowed to specify case values.64

switch ( i ) {5

case 1∼5: // 1, 2, 3, 4, 56

...7

case 10∼15: // 10, 11, 12, 13, 14, 158

...9

}10

Lists of subranges are also allowed.11

case 1∼5, 12∼21, 35∼42:12

9.3 switch Statement13

C allows a number of questionable forms for the switch statement:14

1. By default, the end of a case clause7 falls through to the next case clause in the switch statement; to15

exit a switch statement from a case clause requires explicitly terminating the clause with a transfer16

statement, most commonly break:17

switch ( i ) {18

case 1:19

...20

// fall through21

case 2:22

...23

break; // exit switch statement24

}25

The ability to fall-through to the next clause is a useful form of control flow, specifically when a26

sequence of case actions compound:27

6 gcc has the same mechanism but awkward syntax, 2 ...42, because a space is required after a number, otherwise the period is a

decimal point.7 In this section, the term case clause refers to either a case or default clause.

Page 13: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

9.3 switch Statement 9

switch ( argc ) {case 3:

// open output file// fall through

case 2:

// open input filebreak; // exit switch statement

default:

// usage message}

if ( argc == 3 ) {

// open output file// open input file

} else if ( argc == 2 ) {

// open input file (duplicate)

} else {

// usage message}

1

In this example, case 2 is always done if case 3 is done. This control flow is difficult to simulate with2

if statements or a switch statement without fall-through as code must be duplicated or placed in a3

separate routine. C also uses fall-through to handle multiple case-values resulting in the same action:4

switch ( i ) {5

case 1: case 3: case 5: // odd values6

// odd action7

break;8

case 2: case 4: case 6: // even values9

// even action10

break;11

}12

However, this situation is handled in other languages without fall-through by allowing a list of case13

values. While fall-through itself is not a problem, the problem occurs when fall-through is the default,14

as this semantics is unintuitive to many programmers and is different from virtually all other program-15

ming languages with a switch statement. Hence, default fall-through semantics results in a large16

number of programming errors as programmers often forget the break statement at the end of a case17

clause, resulting in inadvertent fall-through.18

2. It is possible to place case clauses on statements nested within the body of the switch statement:19

switch ( i ) {20

case 0:21

if ( j < k ) {22

...23

case 1: // transfer into "if" statement24

...25

} // if26

case 2:27

while ( j < 5 ) {28

...29

case 3: // transfer into "while" statement30

...31

} // while32

} // switch33

The problem with this usage is branching into control structures, which is known to cause both34

comprehension and technical difficulties. The comprehension problem occurs from the inability to35

determine how control reaches a particular point due to the number of branches leading to it. The36

technical problem results from the inability to ensure declaration and initialization of variables when37

blocks are not entered at the beginning. There are no positive arguments for this kind of control flow,38

and therefore, there is a strong impetus to eliminate it. Nevertheless, C does have an idiom where this39

Page 14: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

10 9.3 switch Statement

capability is used, known as “Duff’s device” [12]:1

register int n = (count + 7) / 8;2

switch ( count % 8 ) {3

case 0: do{ *to = *from++;4

case 7: *to = *from++;5

case 6: *to = *from++;6

case 5: *to = *from++;7

case 4: *to = *from++;8

case 3: *to = *from++;9

case 2: *to = *from++;10

case 1: *to = *from++;11

} while ( n > 0 );12

}13

which unrolls a loop N times (N = 8 above) and uses the switch statement to deal with any iterations14

not a multiple of N. While efficient, this sort of special purpose usage is questionable:15

Disgusting, no? But it compiles and runs just fine. I feel a combination of pride and16

revulsion at this discovery. [12]17

3. It is possible to place the default clause anywhere in the list of labelled clauses for a switch statement,18

rather than only at the end. Virtually all programming languages with a switch statement require the19

default clause to appear last in the case-clause list. The logic for this semantics is that after checking20

all the case clauses without success, the default clause is selected; hence, physically placing the21

default clause at the end of the case clause list matches with this semantics. This physical placement22

can be compared to the physical placement of an else clause at the end of a series of connected if/else23

statements.24

4. It is possible to place unreachable code at the start of a switch statement, as in:25

switch ( x ) {26

int y = 1; // unreachable initialization27

x = 7; // unreachable code without label/branch28

case 0: ...29

...30

int z = 0; // unreachable initialization, cannot appear after case31

z = 2;32

case 1:33

x = z; // without fall through, z is uninitialized34

}35

While the declaration of the local variable y is useful with a scope across all case clauses, the initial-36

ization for such a variable is defined to never be executed because control always transfers over it.37

Furthermore, any statements before the first case clause can only be executed if labelled and trans-38

ferred to using a goto, either from outside or inside of the switch, both of which are problematic. As39

well, the declaration of z cannot occur after the case because a label can only be attached to a state-40

ment, and without a fall through to case 3, z is uninitialized. The key observation is that the switch41

statement branches into control structure, i.e., there are multiple entry points into its statement body.42

Before discussing potential language changes to deal with these problems, it is worth observing that in43

a typical C program:44

• the number of switch statements is small,45

Page 15: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

9.3 switch Statement 11

• most switch statements are well formed (i.e., no Duff’s device),1

• the default clause is usually written as the last case-clause,2

• and there is only a medium amount of fall-through from one case clause to the next, and most of these3

result from a list of case values executing common code, rather than a sequence of case actions that4

compound.5

These observations put into perspective the C

A

changes to the switch.6

1. Eliminating default fall-through has the greatest potential for affecting existing code. However, even7

if fall-through is removed, most switch statements would continue to work because of the explicit8

transfers already present at the end of each case clause, the common placement of the default clause9

at the end of the case list, and the most common use of fall-through, i.e., a list of case clauses10

executing common code, e.g.:11

case 1: case 2: case 3: ...12

still works. Nevertheless, reversing the default action would have a non-trivial effect on case actions13

that compound, such as the above example of processing shell arguments. Therefore, to preserve14

backwards compatibility, it is necessary to introduce a new kind of switch statement, called choose,15

with no implicit fall-through semantics and an explicit fall-through if the last statement of a case-16

clause ends with the new keyword fallthrough/fallthru, e.g.:17

choose ( i ) {18

case 1: case 2: case 3:19

...20

// implicit end of switch (break)21

case 5:22

...23

fallthru; // explicit fall through24

case 7:25

...26

break // explicit end of switch (redundant)27

default:28

j = 3;29

}30

Like the switch statement, the choose statement retains the fall-through semantics for a list of case31

clauses; An implicit break is applied only at the end of the statements following a case clause. An32

explicit fallthru is retained because it is a C-idiom most C programmers expect, and its absence might33

discourage programmers from using the choose statement. As well, allowing an explicit break from34

the choose is a carry over from the switch statement, and expected by C programmers.35

2. Duff’s device is eliminated from both switch and choose statements, and only invalidates a small36

amount of very questionable code. Hence, the case clause must appear at the same nesting level as37

the switch/choose body, as is done in most other programming languages with switch statements.38

3. The issue of default at locations other than at the end of the cause clause can be solved by using good39

programming style, and there are a few reasonable situations involving fall-through where the default40

clause needs to appear is locations other than at the end. Therefore, no change is made for this issue.41

4. Dealing with unreachable code in a switch/choose body is solved by restricting declarations and42

associated initialization to the start of statement body, which is executed before the transfer to the43

Page 16: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

12 9.5 Loop Control

appropriate case clause8 and precluding statements before the first case clause. Further declarations1

at the same nesting level as the statement body are disallowed to ensure every transfer into the body2

is sound.3

switch ( x ) {4

int i = 0; // allowed only at start5

case 0:6

...7

int j = 0; // disallowed8

case 1:9

{10

int k = 0; // allowed at different nesting levels11

...12

case 2: // disallow case in nested statements13

}14

...15

}16

9.4 Non-terminating and Labelled fallthrough17

The fallthrough clause may be non-terminating within a case clause or have a target label to common code18

from multiple case clauses.19

choose ( ... ) {case 3:

if ( ... ) {

... fallthru; // goto case 4} else {

...}

// implicit break

case 4:

choose ( ... ) {case 3:

... fallthrough common;

case 4:... fallthrough common;

common: // below fallthrough

// at case clause level

... // common code for cases 3/4// implicit break

case 4:

choose ( ... ) {case 3:

choose ( ... ) {

case 4:for ( ... ) {

// multi level transfer... fallthru common;

}

...}

...

common: // below fallthrough// at case clause level

20

The target label must be below the fallthrough and may not be nested in a control structure, and the target21

label must be at the same or higher level as the containing case clause and located at the same level as22

a case clause; the target label may be case default, but only associated with the current switch/choose23

statement.24

9.5 Loop Control25

The for/while/do while loop-control allows empty or simplified ranges (see Figure 2).26

• The loop index is polymorphic in the type of the comparison value N (when the start value is implicit)27

or the start value M.28

• An empty conditional implies comparison value of 1 (true).29

• A comparison N is implicit up-to exclusive range [0,N).30

8 Essentially, these declarations are hoisted before the switch/choose statement and both declarations and statement are surrounded

by a compound statement.

Page 17: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

9.6 Labelled continue / break Statement 13

• A comparison = N is implicit up-to inclusive range [0,N].1

• The up-to range M ∼ N means exclusive range [M,N).2

• The up-to range M ∼= N means inclusive range [M,N].3

• The down-to range M ∼ N means exclusive range [N,M).4

• The down-to range M ∼= N means inclusive range [N,M].5

• 0 is the implicit start value;6

• 1 is the implicit increment value.7

• The up-to range uses operator += for increment;8

• The down-to range uses operator = for decrement.9

• @ means put nothing in this field.10

• : means start another index.11

9.6 Labelled continue / break Statement12

While C provides continue and break statements for altering control flow, both are restricted to one level13

of nesting for a particular control structure. Unfortunately, this restriction forces programmers to use goto14

to achieve the equivalent control-flow for more than one level of nesting. To prevent having to switch to the15

goto, C

A

extends the continue and break with a target label to support static multi-level exit [4], as in Java.16

For both continue and break, the target label must be directly associated with a for, while or do statement;17

for break, the target label can also be associated with a switch, if or compound ({}) statement. Figure 3,18

p. 15 shows continue and break indicating the specific control structure, and the corresponding C program19

using only goto and labels. The innermost loop has 7 exit points, which cause continuation or termination20

of one or more of the 7 nested control-structures.21

Both labelled continue and break are a goto restricted in the following ways:22

• They cannot create a loop, which means only the looping constructs cause looping. This restriction23

means all situations resulting in repeated execution are clearly delineated.24

• They cannot branch into a control structure. This restriction prevents missing declarations and/or initial-25

izations at the start of a control structure resulting in undefined behaviour.26

The advantage of the labelled continue/break is allowing static multi-level exits without having to use the27

goto statement, and tying control flow to the target control structure rather than an arbitrary point in a28

program. Furthermore, the location of the label at the beginning of the target control structure informs the29

reader (eye candy) that complex control-flow is occurring in the body of the control structure. With goto,30

the label is at the end of the control structure, which fails to convey this important clue early enough to the31

reader. Finally, using an explicit target for the transfer instead of an implicit target allows new constructs32

to be added or removed without affecting existing constructs. Otherwise, the implicit targets of the current33

continue and break, i.e., the closest enclosing loop or switch, change as certain constructs are added or34

removed.35

10 with Statement36

Grouping heterogeneous data into aggregates (structure/union) is a common programming practice, and an37

aggregate can be further organized into more complex structures, such as arrays and containers:38

struct S { // aggregate39

char c; // fields40

int i;41

double d;42

Page 18: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

14 10 with Statement

loop control output

while () { sout | "empty"; break; }

do { sout | "empty"; break; } while ();for () { sout | "empty"; break; }

for ( 0 ) { sout | "A"; } sout | "zero";

for ( 1 ) { sout | "A"; }for ( 10 ) { sout | "A"; }

for ( = 10 ) { sout | "A"; }

for ( 1 ∼= 10 ∼ 2 ) { sout | "B"; }for ( 10 ∼= 1 ∼ 2 ) { sout | "C"; }

for ( 0.5 ∼ 5.5 ) { sout | "D"; }for ( 5.5 ∼ 0.5 ) { sout | "E"; }

for ( i; 10 ) { sout | i; }

for ( i; = 10 ) { sout | i; }for ( i; 1 ∼= 10 ∼ 2 ) { sout | i; }

for ( i; 10 ∼= 1 ∼ 2 ) { sout | i; }for ( i; 0.5 ∼ 5.5 ) { sout | i; }

for ( i; 5.5 ∼ 0.5 ) { sout | i; }

for ( ui; 2u ∼= 10u ∼ 2u ) { sout | ui; }for ( ui; 10u ∼= 2u ∼ 2u ) { sout | ui; }

enum { N = 10 };

for ( N ) { sout | "N"; }for ( i; N ) { sout | i; }

for ( i; N ∼ 0 ) { sout | i; }const int start = 3, comp = 10, inc = 2;

for ( i; start ∼ comp ∼ inc + 1 ) { sout | i; }

for ( i; 1 ∼ @ ) { if ( i > 10 ) break; sout | i; }for ( i; 10 ∼ @ ) { if ( i < 0 ) break; sout | i; }

for ( i; 2 ∼ @ ∼ 2 ) { if ( i > 10 ) break; sout | i; }for ( i; 2.1 ∼ @ ∼ @ ) { if ( i > 10.5 ) break; sout | i; i += 1.7; }

for ( i; 10 ∼ @ ∼ 2 ) { if ( i < 0 ) break; sout | i; }

for ( i; 12.1 ∼ @ ∼ @ ) { if ( i < 2.5 ) break; sout | i; i = 1.7; }for ( i; 5 : j; 5 ∼ @ ) { sout | i | j; }

for ( i; 5 : j; 5 ∼ @ ) { sout | i | j; }

for ( i; 5 : j; 5 ∼ @ ∼ 2 ) { sout | i | j; }for ( i; 5 : j; 5 ∼ @ ∼ 2 ) { sout | i | j; }

for ( i; 5 : j; 5 ∼ @ ) { sout | i | j; }for ( i; 5 : j; 5 ∼ @ ) { sout | i | j; }

for ( i; 5 : j; 5 ∼ @ ∼ 2 ) { sout | i | j; }

for ( i; 5 : j; 5 ∼ @ ∼ 2 ) { sout | i | j; }for ( i; 5 : j; 5 ∼ @ ∼ 2 : k; 1.5 ∼ @ ) { sout | i | j | k; }

for ( i; 5 : j; 5 ∼ @ ∼ 2 : k; 1.5 ∼ @ ) { sout | i | j | k; }

for ( i; 5 : k; 1.5 ∼ @ : j; 5 ∼ @ ∼ 2 ) { sout | i | j | k; }

empty

emptyempty

zero

AA A A A A A A A A A

A A A A A A A A A A A

B B B B BC C C C C

D D D D DE E E E E

0 1 2 3 4 5 6 7 8 9

0 1 2 3 4 5 6 7 8 9 101 3 5 7 9

10 8 6 4 20.5 1.5 2.5 3.5 4.5

5.5 4.5 3.5 2.5 1.5

2 4 6 8 1010 8 6 4 2

N N N N N N N N N N0 1 2 3 4 5 6 7 8 9

10 9 8 7 6 5 4 3 2 1

3 6 9

1 2 3 4 5 6 7 8 9 1010 9 8 7 6 5 4 3 2 1 0

2 4 6 8 102.1 3.8 5.5 7.2 8.9

10 8 6 4 2 0

12.1 10.4 8.7 7. 5.3 3.60 5 1 4 2 3 3 2 4 1

0 5 1 6 2 7 3 8 4 9

0 5 1 3 2 1 3 1 4 30 5 1 7 2 9 3 11 4 13

0 5 1 4 2 3 3 2 4 10 5 1 6 2 7 3 8 4 9

0 5 1 3 2 1 3 1 4 3

0 5 1 7 2 9 3 11 4 130 5 1.5 1 7 2.5 2 9 3.5 3 11 4.5 4 13 5.5

0 5 1.5 1 7 2.5 2 9 3.5 3 11 4.5 4 13 5.5

0 5 1.5 1 7 2.5 2 9 3.5 3 11 4.5 4 13 5.5

Figure 2: Loop Control Examples

Page 19: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

10 with Statement 15

C

A

C

LC: {... declarations ...

LS: switch ( ... ) {case 3:

LIF: if ( ... ) {

LF: for ( ... ) {LW: while ( ... ) {

... break LC; ...

... break LS; ...

... break LIF; ...

... continue LF; ...

... break LF; ...

... continue LW; ...

... break LW; ...} // while

} // for} else {

... break LIF; ...

} // if} // switch

} // compound

{... declarations ...

switch ( ... ) {case 3:

if ( ... ) {

for ( ... ) {while ( ... ) {

... goto LC; ...

... goto LS; ...

... goto LIF; ...

... goto LFC; ...

... goto LFB; ...

... goto LWC; ...

... goto LWB; ...LWC: ; } LWB: ;

LFC: ; } LFB: ;} else {

... goto LIF; ...

} L3: ;} LS: ;

} LC: ;

// terminate compound// terminate switch

// terminate if

// continue loop// terminate loop

// continue loop

// terminate loop

// terminate if

Figure 3: Multi-level Exit

};1

S s, as[10];2

However, functions manipulating aggregates must repeat the aggregate name to access its containing fields:3

void f( S s ) {4

s.c; s.i; s.d; // access containing fields5

}6

which extends to multiple levels of qualification for nested aggregates. A similar situation occurs in object-7

oriented programming, e.g., C++:8

struct S {9

char c; // fields10

int i;11

double d;12

void f() { // implicit “this” aggregate13

this >c; this >i; this >d; // access containing fields14

}15

}16

Object-oriented nesting of member functions in a class/struct allows eliding this > because of lexical17

scoping. However, for other aggregate parameters, qualification is necessary:18

struct T { double m, n; };19

int S::f( T & t ) { // multiple aggregate parameters20

c; i; d; // this–>.c, this–>.i, this–>.d21

t.m; t.n; // must qualify22

}23

To simplify the programmer experience, C

A

provides a with statement (see Pascal [23, § 4.F]) to elide24

Page 20: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

16 10 with Statement

aggregate qualification to fields by opening a scope containing the field identifiers. Hence, the qualified1

fields become variables with the side-effect that it is easier to optimizing field references in a block.2

void f( S & this ) with ( this ) { // with statement3

c; i; d; // this.c, this.i, this.d4

}5

with the generality of opening multiple aggregate-parameters:6

void f( S & s, T & t ) with ( s, t ) { // multiple aggregate parameters7

c; i; d; // s.c, s.i, s.d8

m; n; // t.m, t.n9

}10

In detail, the with statement has the form:11

with-statement :12

'with' '(' expression-list ')' compound-statement13

and may appear as the body of a function or nested within a function body. Each expression in the14

expression-list provides a type and object. The type must be an aggregate type. (Enumerations are already15

opened.) The object is the implicit qualifier for the open structure-fields.16

All expressions in the expression list are open in parallel within the compound statement. This semantic17

is different from Pascal, which nests the openings from left to right. The difference between parallel and18

nesting occurs for fields with the same name and type:19

struct S { int i; int j; double m; } s, w;20

struct T { int i; int k; int m; } t, w;21

with ( s, t ) {22

j + k; // unambiguous, s.j + t.k23

m = 5.0; // unambiguous, t.m = 5.024

m = 1; // unambiguous, s.m = 125

int a = m; // unambiguous, a = s.i26

double b = m; // unambiguous, b = t.m27

int c = s.i + t.i; // unambiguous, qualification28

(double)m; // unambiguous, cast29

}30

For parallel semantics, both s.i and t.i are visible, so i is ambiguous without qualification; for nested seman-31

tics, t.i hides s.i, so i implies t.i. C

A

’s ability to overload variables means fields with the same name32

but different types are automatically disambiguated, eliminating most qualification when opening multiple33

aggregates. Qualification or a cast is used to disambiguate.34

There is an interesting problem between parameters and the function-body with, e.g.:35

void ?{}( S & s, int i ) with ( s ) { // constructor36

s.i = i; j = 3; m = 5.5; // initialize fields37

}38

Here, the assignment s.i = i means s.i = s.i, which is meaningless, and there is no mechanism to qualify39

the parameter i, making the assignment impossible using the function-body with. To solve this problem,40

parameters are treated like an initialized aggregate:41

struct Params {42

S & s;43

int i;44

} params;45

and implicitly opened after a function-body open, to give them higher priority:46

void ?{}( S & s, int i ) with ( s ) with( params ) {47

Page 21: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

10 with Statement 17

s.i = i; j = 3; m = 5.5;1

}2

Finally, a cast may be used to disambiguate among overload variables in a with expression:3

with ( w ) { ... } // ambiguous, same name and no context4

with ( (S)w ) { ... } // unambiguous, cast5

and with expressions may be complex expressions with type reference (see Section ??) to aggregate:6

In object-oriented programming, there is an implicit first parameter, often names self or this, which is7

elided.8

class C {9

int i, j;10

int mem() { // implicit "this" parameter11

i = 1; // this->i12

j = 2; // this->j13

}14

}15

Since C

A

is non-object-oriented, the equivalent object-oriented program looks like:16

struct S { int i, j; };17

int mem( S & this ) { // explicit "this" parameter18

this.i = 1; // "this" is not elided19

this.j = 2;20

}21

but it is cumbersome having to write “this.” many times in a member.22

C

A

provides a with clause/statement (see Pascal [23, § 4.F]) to elided the "this." by opening a scope23

containing field identifiers, changing the qualified fields into variables and giving an opportunity for opti-24

mizing qualified references.25

int mem( S & this ) with( this ) { // with clause26

i = 1; // this.i27

j = 2; // this.j28

}29

which extends to multiple routine parameters:30

struct T { double m, n; };31

int mem2( S & this1, T & this2 ) with( this1, this2 ) {32

i = 1; j = 2;33

m = 1.0; n = 2.0;34

}35

The statement form is used within a block:36

int foo() {37

struct S1 { ... } s1;38

struct S2 { ... } s2;39

with( s1 ) { // with statement40

// access fields of s1 without qualification41

with s2 { // nesting42

// access fields of s1 and s2 without qualification43

}44

}45

with s1, s2 {46

// access unambiguous fields of s1 and s2 without qualification47

}48

Page 22: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

18 11.1 Exception Hierarchy

}1

When opening multiple structures, fields with the same name and type are ambiguous and must be fully2

qualified. For fields with the same name but different type, context/cast can be used to disambiguate.3

struct S { int i; int j; double m; } a, c;4

struct T { int i; int k; int m } b, c;5

with( a, b )6

{7

}8

11 Exception Handling9

Exception handling provides two mechanism: change of control flow from a raise to a handler, and commu-10

nication from the raise to the handler. Transfer of control can be local, within a routine, or non-local, among11

routines. Non-local transfer can cause stack unwinding, i.e., non-local routine termination, depending on12

the kind of raise.13

exception t E {}; // exception type14

void f(...) {15

... throw E{}; ... // termination16

... throwResume E{}; ... // resumption17

}18

try {19

f(...);20

} catch( E e ; boolean-predicate ) { // termination handler21

// recover and continue22

} catchResume( E e ; boolean-predicate ) { // resumption handler23

// repair and return24

} finally {25

// always executed26

}27

The kind of raise and handler match: throw with catch and throwResume with catchResume. Then the28

exception type must match along with any additonal predicate must be true. The catch and catchResume29

handlers may appear in any oder. However, the finally clause must appear at the end of the try statement.30

11.1 Exception Hierarchy31

An exception type can be derived from another exception type, just like deriving a subclass from a class,32

providing a kind of polymorphism among exception types. The exception-type hierarchy that is created is33

used to organize exception types, similar to a class hierarchy in object-oriented languages, e.g.:34

IO Arithmetic

File Network DivideByZero Overflow Underflow

Exception

35

A programmer can then choose to handle an exception at different degrees of specificity along the hierarchy;36

derived exception-types support a more flexible programming style. For example, higher-level code should37

catch general exceptions to reduce coupling to the specific implementation at the lower levels; unnecessary38

coupling may force changes in higher-level code when low-level code changes. A consequence of derived39

exception-types is that multiple exceptions may match, e.g.:40

Page 23: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

12 Alternative Declarations 19

catch( Arithmetic )1

matches all three derived exception-types: DivideByZero, Overflow, and Underflow. Because the propagation2

mechanisms perform a simple linear search of the handler clause for a guarded block, and selects the first3

matching handler, the order of catch clauses in the handler clause becomes important, e.g.:4

try {5

...6

} catch( Overflow ) { // must appear first7

// handle overflow8

} catch( Arithmetic )9

// handle other arithmetic issues10

}11

Multiple derivation among exception is not supported.12

12 Alternative Declarations13

C declaration syntax is notoriously confusing and error prone. For example, many C programmers are14

confused by a declaration as simple as:15

int * x[5] 0 1 2 3 4

0 1 2 3 4

x x16

Is this an array of 5 pointers to integers or a pointer to an array of 5 integers? If there is any doubt, it implies17

productivity and safety issues even for basic programs. Another example of confusion results from the fact18

that a routine name and its parameters are embedded within the return type, mimicking the way the return19

value is used at the routine’s call site. For example, a routine returning a pointer to an array of integers is20

defined and used in the following way:21

int (*f())[5] {...}; // definition22

... (*f())[3] += 1; // usage23

Essentially, the return type is wrapped around the routine name in successive layers (like an onion). While24

attempting to make the two contexts consistent is a laudable goal, it has not worked out in practice, even25

though Dennis Richie believed otherwise:26

In spite of its difficulties, I believe that the C’s approach to declarations remains plausible, and27

am comfortable with it; it is a useful unifying principle. [26, p. 12]28

C

A

provides its own type, variable and routine declarations, using a different syntax. The new declara-29

tions place qualifiers to the left of the base type, while C declarations place qualifiers to the right of the base30

type. In the following example, red is the base type and blue is qualifiers. The C

A

declarations move the31

qualifiers to the left of the base type, i.e., move the blue to the left of the red, while the qualifiers have the32

same meaning but are ordered left to right to specify a variable’s type.33

C

A

C

[5] * int x1;

* [5] int x2;

[* [5] int] f( int p );

int * x1 [5];int (*x2)[5];

int (*f( int p ))[5];

34

The only exception is bit field specification, which always appear to the right of the base type. However,35

unlike C, C

A

type declaration tokens are distributed across all variables in the declaration list. For instance,36

variables x and y of type pointer to integer are defined in C

A

as follows:37

C

A

C

* int x, y; int *x, *y;38

Page 24: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

20 13 Pointer / Reference

The downside of this semantics is the need to separate regular and pointer declarations:1

C

A

C

* int x;int y;

int *x, y;2

which is prescribing a safety benefit. Other examples are:3

C

A

C

[ 5 ] int z;[ 5 ] * char w;

* [ 5 ] double v;

struct s {int f0:3;

* int f1;[ 5 ] * int f2;

};

int z[ 5 ];char * w[ 5 ];

double (* v)[ 5 ];

struct s {int f0:3;

int * f1;int * f2[ 5 ]

};

// array of 5 integers// array of 5 pointers to char

// pointer to array of 5 doubles

// common bit field syntax

4

All type qualifiers, e.g., const, volatile, etc., are used in the normal way with the new declarations and5

also appear left to right, e.g.:6

C

A

C

const * const int x;

const * [ 5 ] const int y;

int const * const x;

const int (* const y)[ 5 ]

// const pointer to const integer

// const pointer to array of 5 const integers

7

All declaration qualifiers, e.g., extern, static, etc., are used in the normal way with the new declarations but8

can only appear at the start of a C

A

routine declaration,9 e.g.:9

C

A

C

extern [ 5 ] int x;

static * const int y;

int extern x[ 5 ];

const int static * y;

// externally visible array of 5 integers

// internally visible pointer to constant int

10

The new declaration syntax can be used in other contexts where types are required, e.g., casts and the11

pseudo-routine sizeof:12

C

A

C

y = (* int)x;

i = sizeof([ 5 ] * int);

y = (int *)x;

i = sizeof(int * [ 5 ]);

13

Finally, new C

A

declarations may appear together with C declarations in the same program block, but14

cannot be mixed within a specific declaration. Therefore, a programmer has the option of either continuing15

to use traditional C declarations or take advantage of the new style. Clearly, both styles need to be supported16

for some time due to existing C-style header-files, particularly for UNIX-like systems.17

13 Pointer / Reference18

C provides a pointer type; C

A

adds a reference type. These types may be derived from an object or routine19

type, called the referenced type. Objects of these types contain an address, which is normally a location in20

memory, but may also address memory-mapped registers in hardware devices. An integer constant expres-21

sion with the value 0, or such an expression cast to type void *, is called a null-pointer constant.10 An address22

is sound, if it points to a valid memory location in scope, i.e., within the program’s execution-environment23

9 The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent

feature. [6, § 6.11.5(1)]10 One way to conceptualize the null pointer is that no variable is placed at this address, so the null-pointer address can be used to

denote an uninitialized pointer/reference object; i.e., the null pointer is guaranteed to compare unequal to a pointer to any object or

routine. In general, a value with special meaning among a set of values is called a sentinel value, e.g., 1 as a return code value.

Page 25: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

13 Pointer / Reference 21

and has not been freed. Dereferencing an unsound address, including the null pointer, is undefined, often1

resulting in a memory fault.2

A program object is a region of data storage in the execution environment, the contents of which can3

represent values. In most cases, objects are located in memory at an address, and the variable name for an4

object is an implicit address to the object generated by the compiler and automatically dereferenced, as in:5

int x;

x = 3;

int y;y = x;

3

3104

100x

yint

int int * const x = (int *)100

*x = 3; // implicit dereference

int * const y = (int *)104;

*y = *x; // implicit dereference

6

where the right example is how the compiler logically interprets the variables in the left example. Since a7

variable name only points to one address during its lifetime, it is an immutable pointer; hence, the implicit8

type of pointer variables x and y are constant pointers in the compiler interpretation. In general, variable9

addresses are stored in instructions instead of loaded from memory, and hence may not occupy storage.10

These approaches are contrasted in the following:11

explicit variable address implicit variable address

lda r1,100 // load address of x

ld r2,(r1) // load value of xlda r3,104 // load address of y

st r2,(r3) // store x into y

ld r2,(100) // load value of x

st r2,(104) // store x into y

12

Finally, the immutable nature of a variable’s address and the fact that there is no storage for the variable13

pointer means pointer assignment is impossible. Therefore, the expression x = y has only one meaning,14

*x = *y, i.e., manipulate values, which is why explicitly writing the dereferences is unnecessary even though15

it occurs implicitly as part of instruction decoding.16

A pointer/reference object is a generalization of an object variable-name, i.e., a mutable address that17

can point to more than one memory location during its lifetime. (Similarly, an integer variable can contain18

multiple integer literals during its lifetime versus an integer constant representing a single literal during its19

lifetime, and like a variable name, may not occupy storage if the literal is embedded directly into instruc-20

tions.) Hence, a pointer occupies memory to store its current address, and the pointer’s value is loaded by21

dereferencing, e.g.:22

int x, y, * p1, * p2, ** p3;

p1 = &x; // p1 points to xp2 = p1; // p2 points to x

p1 = &y; // p1 points to y

p3 = &p2; // p3 points to p2 104y

int112

p23 int *100

100x

int108

p13 int *

116p3

104 112 int **

23

Notice, an address has a duality: a location in memory or the value at that location. In many cases,24

a compiler might be able to infer the best meaning for these two cases. For example, Algol68 [24] infers25

pointer dereferencing to select the best meaning for each pointer usage26

p2 = p1 + x; // compiler infers *p2 = *p1 + x;27

Algol68 infers the following dereferencing *p2 = *p1 + x, because adding the arbitrary integer value in x to28

the address of p1 and storing the resulting address into p2 is an unlikely operation. Unfortunately, automatic29

dereferencing does not work in all cases, and so some mechanism is necessary to fix incorrect choices.30

Rather than inferring dereference, most programming languages pick one implicit dereferencing seman-31

tics, and the programmer explicitly indicates the other to resolve address-duality. In C, objects of pointer32

type always manipulate the pointer object’s address:33

p1 = p2; // p1 = p2 rather than *p1 = *p234

p2 = p1 + x; // p2 = p1 + x rather than *p2 = *p1 + x35

Page 26: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

22 13 Pointer / Reference

even though the assignment to p2 is likely incorrect, and the programmer probably meant:1

p1 = p2; // pointer address assignment2

*p2 = *p1 + x; // pointed-to value assignment / operation3

The C semantics work well for situations where manipulation of addresses is the primary meaning and data4

is rarely accessed, such as storage management (malloc/free).5

However, in most other situations, the pointed-to value is requested more often than the pointer address.6

*p2 = ((*p1 + *p2) * (**p3 *p1)) / (**p3 15);7

In this case, it is tedious to explicitly write the dereferencing, and error prone when pointer arithmetic is8

allowed. It is better to have the compiler generate the dereferencing and have no implicit pointer arithmetic:9

p2 = ((p1 + p2) * (p3 p1)) / (p3 15);10

To support this common case, a reference type is introduced in C

A

, denoted by &, which is the opposite11

dereference semantics to a pointer type, making the value at the pointed-to location the implicit semantics12

for dereferencing (similar but not the same as C++ reference types).13

int x, y, & r1, & r2, && r3;14

&r1 = &x; // r1 points to x15

&r2 = &r1; // r2 points to x16

&r1 = &y; // r1 points to y17

&&r3 = &&r2; // r3 points to r218

r2 = ((r1 + r2) * (r3 r1)) / (r3 15); // implicit dereferencing19

Except for auto-dereferencing by the compiler, this reference example is the same as the previous pointer20

example. Hence, a reference behaves like the variable name for the current variable it is pointing-to. One21

way to conceptualize a reference is via a rewrite rule, where the compiler inserts a dereference operator22

before the reference variable for each reference qualifier in a declaration, so the previous example becomes:23

*r2 = ((*r1 + *r2) * (**r3 *r1)) / (**r3 15);24

When a reference operation appears beside a dereference operation, e.g., &*, they cancel out. However, in C,25

the cancellation always yields a value (rvalue).11 For a C

A

reference type, the cancellation on the left-hand26

side of assignment leaves the reference as an address (lvalue):27

(&*)r1 = &x; // (&*) cancel giving address in r1 not variable pointed-to by r128

Similarly, the address of a reference can be obtained for assignment or computation (rvalue):29

(&(&*)*)r3 = &(&*)r2; // (&*) cancel giving address in r2, (&(&*)*) cancel giving address in r330

Cancellation works to arbitrary depth.31

Fundamentally, pointer and reference objects are functionally interchangeable because both contain32

addresses.33

int x, *p1 = &x, **p2 = &p1, ***p3 = &p2,34

&r1 = x, &&r2 = r1, &&&r3 = r2;35

***p3 = 3; // change x36

r3 = 3; // change x, ***r337

**p3 = ...; // change p138

&r3 = ...; // change r1, (&*)**r3, 1 cancellation39

*p3 = ...; // change p240

&&r3 = ...; // change r2, (&(&*)*)*r3, 2 cancellations41

&&&r3 = p3; // change r3 to p3, (&(&(&*)*)*)r3, 3 cancellations42

11 The unary & operator yields the address of its operand. If the operand has type “type”, the result has type “pointer to type”. If

the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were

omitted, except that the constraints on the operators still apply and the result is not an lvalue. [6, § 6.5.3.2–3]

Page 27: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

13.1 Initialization 23

Furthermore, both types are equally performant, as the same amount of dereferencing occurs for both types.1

Therefore, the choice between them is based solely on whether the address is dereferenced frequently or2

infrequently, which dictates the amount of implicit dereferencing aid from the compiler.3

As for a pointer type, a reference type may have qualifiers:4

const int cx = 5; // cannot change cx;5

const int & cr = cx; // cannot change what cr points to6

&cr = &cx; // can change cr7

cr = 7; // error, cannot change cx8

int & const rc = x; // must be initialized9

&rc = &x; // error, cannot change rc10

const int & const crc = cx; // must be initialized11

crc = 7; // error, cannot change cx12

&crc = &cx; // error, cannot change crc13

Hence, for type & const, there is no pointer assignment, so &rc = &x is disallowed, and the address value14

cannot be the null pointer unless an arbitrary pointer is coerced into the reference:15

int & const cr = *0; // where 0 is the int * zero16

Note, constant reference-types do not prevent addressing errors because of explicit storage-management:17

int & const cr = *malloc();18

cr = 5;19

free( &cr );20

cr = 7; // unsound pointer dereference21

The position of the const qualifier after the pointer/reference qualifier causes confuse for C program-22

mers. The const qualifier cannot be moved before the pointer/reference qualifier for C style-declarations;23

C

A

-style declarations (see Section 12, p. 19) attempt to address this issue:24

CA

C

const * const * const int ccp;const & const & const int ccr;

const int * const * const ccp;25

where the C

A

declaration is read left-to-right.26

Finally, like pointers, references are usable and composable with other type operators and generators.27

int w, x, y, z, & ar[3] = { x, y, z }; // initialize array of references28

&ar[1] = &w; // change reference array element29

typeof( ar[1] ) p; // (gcc) is int, i.e., the type of referenced object30

typeof( &ar[1] ) q; // (gcc) is int &, i.e., the type of reference31

sizeof( ar[1] ) == sizeof( int ); // is true, i.e., the size of referenced object32

sizeof( &ar[1] ) == sizeof( int *) // is true, i.e., the size of a reference33

In contrast to C

A

reference types, C++’s reference types are all const references, preventing changes to34

the reference address, so only value assignment is possible, which eliminates half of the address duality.35

Also, C++ does not allow arrays of reference12 Java’s reference types to objects (all Java objects are on the36

heap) are like C pointers, which always manipulate the address, and there is no (bit-wise) object assignment,37

so objects are explicitly cloned by shallow or deep copying, which eliminates half of the address duality.38

13.1 Initialization39

Initialization is different than assignment because initialization occurs on the empty (uninitialized) storage40

on an object, while assignment occurs on possibly initialized storage of an object. There are three initial-41

12 The reason for disallowing arrays of reference is unknown, but possibly comes from references being ethereal (like a textual

macro), and hence, replaceable by the referant object.

Page 28: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

24 13.1 Initialization

ization contexts in C

A

: declaration initialization, argument/parameter binding, return/temporary binding.1

Because the object being initialized has no value, there is only one meaningful semantics with respect to2

address duality: it must mean address as there is no pointed-to value. In contrast, the left-hand side of3

assignment has an address that has a duality. Therefore, for pointer/reference initialization, the initializing4

value must be an address not a value.5

int * p = &x; // assign address of x6

int * p = x; // assign value of x7

int & r = x; // must have address of x8

Like the previous example with C pointer-arithmetic, it is unlikely assigning the value of x into a pointer is9

meaningful (again, a warning is usually given). Therefore, for safety, this context requires an address, so10

it is superfluous to require explicitly taking the address of the initialization object, even though the type is11

incorrect. Note, this is strictly a convenience and safety feature for a programmer. Hence, C

A

allows r to12

be assigned x because it infers a reference for x, by implicitly inserting a address-of operator, &, and it is an13

error to put an & because the types no longer match due to the implicit dereference. Unfortunately, C allows14

p to be assigned with &x (address) or x (value), but most compilers warn about the latter assignment as15

being potentially incorrect. Similarly, when a reference type is used for a parameter/return type, the call-site16

argument does not require a reference operator for the same reason.17

int & f( int & r ); // reference parameter and return18

z = f( x ) + f( y ); // reference operator added, temporaries needed for call results19

Within routine f, it is possible to change the argument by changing the corresponding parameter, and param-20

eter r can be locally reassigned within f. Since operator routine ?+? takes its arguments by value, the21

references returned from f are used to initialize compiler generated temporaries with value semantics that22

copy from the references.23

int temp1 = f( x ), temp2 = f( y );24

z = temp1 + temp2;25

This implicit referencing is crucial for reducing the syntactic burden for programmers when using refer-26

ences; otherwise references have the same syntactic burden as pointers in these contexts.27

When a pointer/reference parameter has a const value (immutable), it is possible to pass literals and28

expressions.29

void f( const int & cr );30

void g( const int * cp );31

f( 3 ); g( &3 );32

f( x + y ); g( &(x + y) );33

Here, the compiler passes the address to the literal 3 or the temporary for the expression x + y, knowing the34

argument cannot be changed through the parameter. The & before the constant/expression for the pointer-35

type parameter (g) is a C

A

extension necessary to type match and is a common requirement before a variable36

in C (e.g., scanf). Importantly, &3 may not be equal to &3, where the references occur across calls because37

the temporaries maybe different on each call.38

C

A

extends this semantics to a mutable pointer/reference parameter, and the compiler implicitly creates39

the necessary temporary (copying the argument), which is subsequently pointed-to by the reference param-40

eter and can be changed.1341

void f( int & r );42

void g( int * p );43

f( 3 ); g( &3 ); // compiler implicit generates temporaries44

f( x + y ); g( &(x + y) ); // compiler implicit generates temporaries45

13 If whole program analysis is possible, and shows the parameter is not assigned, i.e., it is const, the temporary is unnecessary.

Page 29: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

13.2 Address-of Semantics 25

Essentially, there is an implicit rvalue to lvalue conversion in this case.14 The implicit conversion allows1

seamless calls to any routine without having to explicitly name/copy the literal/expression to allow the call.2

Finally, C handles routine objects in an inconsistent way. A routine object is both a pointer and a3

reference (particle and wave).4

void f( int i );5

void (* fp)( int ); // routine pointer6

fp = f; // reference initialization7

fp = &f; // pointer initialization8

fp = *f; // reference initialization9

fp(3); // reference invocation10

(*fp)(3); // pointer invocation11

While C’s treatment of routine objects has similarity to inferring a reference type in initialization contexts,12

the examples are assignment not initialization, and all possible forms of assignment are possible (f, &f, *f)13

without regard for type. Instead, a routine object should be referenced by a const reference:14

const void (& fr)( int ) = f; // routine reference15

fr = ... // error, cannot change code16

&fr = ...; // changing routine reference17

fr( 3 ); // reference call to f18

(*fr)(3); // error, incorrect type19

because the value of the routine object is a routine literal, i.e., the routine code is normally immutable20

during execution.15 C

A

allows this additional use of references for routine objects in an attempt to give a21

more consistent meaning for them.22

13.2 Address-of Semantics23

In C, &E is an rvalue for any expression E. CA

extends the & (address-of) operator as follows:24

• if R is an rvalue of type T &1 · · · &r, where r ≥ 1 references (& symbols), than &R has type T *&2 · · · &r,25

i.e., T pointer with r−1 references (& symbols).26

• if L is an lvalue of type T &1 · · · &l , where l ≥ 0 references (& symbols), than &L has type T *&1 · · · &l ,27

i.e., T pointer with l references (& symbols).28

The following example shows the first rule applied to different rvalue contexts:29

int x, * px, ** ppx, *** pppx, **** ppppx;30

int & rx = x, && rrx = rx, &&& rrrx = rrx ;31

x = rrrx; // rrrx is an lvalue with type int &&& (equivalent to x)32

px = &rrrx; // starting from rrrx, &rrrx is an rvalue with type int *&&& (&x)33

ppx = &&rrrx; // starting from &rrrx, &&rrrx is an rvalue with type int **&& (&rx)34

pppx = &&&rrrx; // starting from &&rrrx, &&&rrrx is an rvalue with type int ***& (&rrx)35

ppppx = &&&&rrrx; // starting from &&&rrrx, &&&&rrrx is an rvalue with type int **** (&rrrx)36

The following example shows the second rule applied to different lvalue contexts:37

int x, * px, ** ppx, *** pppx;38

int & rx = x, && rrx = rx, &&& rrrx = rrx ;39

rrrx = 2; // rrrx is an lvalue with type int &&& (equivalent to x)40

&rrrx = px; // starting from rrrx, &rrrx is an rvalue with type int *&&& (rx)41

&&rrrx = ppx; // starting from &rrrx, &&rrrx is an rvalue with type int **&& (rrx)42

14 This conversion attempts to address the const hell problem, when the innocent addition of a const qualifier causes a cascade of

type failures, requiring an unknown number of additional const qualifiers, until it is discovered a const qualifier cannot be added

and all the const qualifiers must be removed.15 Dynamic code rewriting is possible but only in special circumstances.

Page 30: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

26 14 Routine Definition

&&&rrrx = pppx; // starting from &&rrrx, &&&rrrx is an rvalue with type int ***& (rrrx)1

13.3 Conversions2

C provides a basic implicit conversion to simplify variable usage:3

0. lvalue to rvalue conversion: cv T converts to T, which allows implicit variable dereferencing.4

int x;5

x + 1; // lvalue variable (int) converts to rvalue for expression6

An rvalue has no type qualifiers (cv), so the lvalue qualifiers are dropped.7

C

A

provides three new implicit conversion for reference types to simplify reference usage.8

1. reference to rvalue conversion: cv T & converts to T, which allows implicit reference dereferencing.9

int x, &r = x, f( int p );10

x = r + f( r ); // lvalue reference converts to rvalue11

An rvalue has no type qualifiers (cv), so the reference qualifiers are dropped.12

2. lvalue to reference conversion: lvalue type cv1 T converts to cv2 T &, which allows implicitly converting13

variables to references.14

int x, &r = x, f( int & p ); // lvalue variable (int) convert to reference (int &)15

f( x ); // lvalue variable (int) convert to reference (int &)16

Conversion can restrict a type, where cv1 ≤ cv2, e.g., passing an int to a const volatile int &, which17

has low cost. Conversion can expand a type, where cv1 > cv2, e.g., passing a const volatile int to an18

int &, which has high cost (warning); furthermore, if cv1 has const but not cv2, a temporary variable19

is created to preserve the immutable lvalue.20

3. rvalue to reference conversion: T converts to cv T &, which allows binding references to temporaries.21

int x, & f( int & p );22

f( x + 3 ); // rvalue parameter (int) implicitly converts to lvalue temporary reference (int &)23

&f(...) = &x; // rvalue result (int &) implicitly converts to lvalue temporary reference (int &)24

In both case, modifications to the temporary are inaccessible (warning). Conversion expands the25

temporary-type with cv, which is low cost since the temporary is inaccessible.26

14 Routine Definition27

C

A

also supports a new syntax for routine definition, as well as C11 and K&R routine syntax. The point of28

the new syntax is to allow returning multiple values from a routine [18, 25], e.g.:29

[ int o1, int o2, char o3 ] f( int i1, char i2, char i3 ) {30

routine body31

}32

where routine f has three output (return values) and three input parameters. Existing C syntax cannot be33

extended with multiple return types because it is impossible to embed a single routine name within multiple34

return type specifications.35

In detail, the brackets, [], enclose the result type, where each return value is named and that name is a36

local variable of the particular return type.16 The value of each local return variable is automatically returned37

at routine termination. Declaration qualifiers can only appear at the start of a routine definition, e.g.:38

16 Michael Tiemann, with help from Doug Lea, provided named return values in g++, circa 1989.

Page 31: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

14.1 Named Return Values 27

extern [ int x ] g( int y ) { }1

Lastly, if there are no output parameters or input parameters, the brackets and/or parentheses must still be2

specified; in both cases the type is assumed to be void as opposed to old style C defaults of int return type3

and unknown parameter types, respectively, as in:4

[ ] g(); // no input or output parameters5

[ void ] g( void ); // no input or output parameters6

Routine f is called as follows:7

[ i, j, ch ] = f( 3, 'a', ch );8

The list of return values from f and the grouping on the left-hand side of the assignment is called a return9

list and discussed in Section 12.10

C

A

style declarations cannot be used to declare parameters for K&R style routine definitions because of11

the following ambiguity:12

int (*f(x))[ 5 ] int x; {}13

The string “int (*f(x))[ 5 ]” declares a K&R style routine of type returning a pointer to an array of 5 integers,14

while the string “[ 5 ] int x” declares a C

A

style parameter x of type array of 5 integers. Since the strings15

overlap starting with the open bracket, [, there is an ambiguous interpretation for the string. As well, C

A

-style16

declarations cannot be used to declare parameters for C-style routine-definitions because of the following17

ambiguity:18

typedef int foo;19

int f( int (* foo) ); // foo is redefined as a parameter name20

The string “int (* foo)” declares a C-style named-parameter of type pointer to an integer (the parenthesis are21

superfluous), while the same string declares a C

A

style unnamed parameter of type routine returning integer22

with unnamed parameter of type pointer to foo. The redefinition of a type name in a parameter list is the23

only context in C where the character * can appear to the left of a type name, and CA

relies on all type24

qualifier characters appearing to the right of the type name. The inability to use C

A

declarations in these25

two contexts is probably a blessing because it precludes programmers from arbitrarily switching between26

declarations forms within a declaration contexts.27

C-style declarations can be used to declare parameters for C

A

style routine definitions, e.g.:28

[ int ] f( * int, int * ); // returns an integer, accepts 2 pointers to integers29

[ * int, int * ] f( int ); // returns 2 pointers to integers, accepts an integer30

The reason for allowing both declaration styles in the new context is for backwards compatibility with31

existing preprocessor macros that generate C-style declaration-syntax, as in:32

#define ptoa( n, d ) int (*n)[ d ]33

int f( ptoa( p, 5 ) ) ... // expands to int f( int (*p)[ 5 ] )34

[ int ] f( ptoa( p, 5 ) ) ... // expands to [ int ] f( int (*p)[ 5 ] )35

Again, programmers are highly encouraged to use one declaration form or the other, rather than mixing the36

forms.37

14.1 Named Return Values38

Named return values handle the case where it is necessary to define a local variable whose value is then39

returned in a return statement, as in:40

int f() {41

int x;42

... x = 0; ... x = y; ...43

return x;44

Page 32: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

28 14.2 Routine Prototype

}1

Because the value in the return variable is automatically returned when a C

A

routine terminates, the return2

statement does not contain an expression, as in:3

[ int x, int y ] f() {

int z;... x = 0; ... y = z; ...

return; // implicitly return x, y

}

4

When the return is encountered, the current values of x and y are returned to the calling routine. As well,5

“falling off the end” of a routine without a return statement is permitted, as in:6

[ int x, int y ] f() {7

...8

} // implicitly return x, y9

In this case, the current values of x and y are returned to the calling routine just as if a return had been10

encountered.11

Named return values may be used in conjunction with named parameter values; specifically, a return and12

parameter can have the same name.13

[ int x, int y ] f( int, x, int y ) {14

...15

} // implicitly return x, y16

This notation allows the compiler to eliminate temporary variables in nested routine calls.17

[ int x, int y ] f( int, x, int y ); // prototype declaration18

int a, b;19

[a, b] = f( f( f( a, b ) ) );20

While the compiler normally ignores parameters names in prototype declarations, here they are used to21

eliminate temporary return-values by inferring that the results of each call are the inputs of the next call,22

and ultimately, the left-hand side of the assignment. Hence, even without the body of routine f (separate23

compilation), it is possible to perform a global optimization across routine calls. The compiler warns about24

naming inconsistencies between routine prototype and definition in this case, and behaviour is undefined if25

the programmer is inconsistent.26

14.2 Routine Prototype27

The syntax of the new routine prototype declaration follows directly from the new routine definition syntax;28

as well, parameter names are optional, e.g.:29

[ int x ] f (); // returning int with no parameters30

[ * int ] g (int y); // returning pointer to int with int parameter31

[ ] h ( int, char ); // returning no result with int and char parameters32

[ * int, int ] j ( int ); // returning pointer to int and int, with int parameter33

This syntax allows a prototype declaration to be created by cutting and pasting source text from the routine34

definition header (or vice versa). Like C, it is possible to declare multiple routine-prototypes in a single35

declaration, where the return type is distributed across all routine names in the declaration list (see Section 12,36

p. 19), e.g.:37

C : const double bar1(), bar2( int ), bar3( double );38

C

A

: [const double] foo(), foo( int ), foo( double ) { return 3.0; }39

C

A

allows the last routine in the list to define its body.40

Declaration qualifiers can only appear at the start of a C

A

routine declaration,9 e.g.:41

Page 33: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

15 Routine Pointers 29

extern [ int ] f ( int );1

static [ int ] g ( int );2

15 Routine Pointers3

The syntax for pointers to C

A

routines specifies the pointer name on the right, e.g.:4

* [ int x ] () fp; // pointer to routine returning int with no parameters5

* [ * int ] (int y) gp; // pointer to routine returning pointer to int with int parameter6

* [ ] (int,char) hp; // pointer to routine returning no result with int and char parameters7

* [ * int,int ] ( int ) jp; // pointer to routine returning pointer to int and int, with int parameter8

While parameter names are optional, a routine name cannot be specified; for example, the following is9

incorrect:10

* [ int x ] f () fp; // routine name "f" is not allowed11

16 Named and Default Arguments12

Named and default arguments [22]17 are two mechanisms to simplify routine call. Both mechanisms are13

discussed with respect to C

A

.14

Named (or Keyword) Arguments: provide the ability to specify an argument to a routine call using the15

parameter name rather than the position of the parameter. For example, given the routine:16

void p( int x, int y, int z ) {...}17

a positional call is:18

p( 4, 7, 3 );19

whereas a named (keyword) call may be:20

p( z : 3, x : 4, y : 7 ); // rewrite⇒ p( 4, 7, 3 )21

Here the order of the arguments is unimportant, and the names of the parameters are used to associate22

argument values with the corresponding parameters. The compiler rewrites a named call into a positional23

call. The advantages of named parameters are:24

• Remembering the names of the parameters may be easier than the order in the routine definition.25

• Parameter names provide documentation at the call site (assuming the names are descriptive).26

• Changes can be made to the order or number of parameters without affecting the call (although the27

call must still be recompiled).28

Unfortunately, named arguments do not work in C-style programming-languages because a routine29

prototype is not required to specify parameter names, nor do the names in the prototype have to match30

with the actual definition. For example, the following routine prototypes and definition are all valid.31

void p( int, int, int ); // equivalent prototypes32

void p( int x, int y, int z );33

void p( int y, int x, int z );34

void p( int z, int y, int x );35

void p( int q, int r, int s ) {} // match with this definition36

17 Francez [17] proposed a further extension to the named-parameter passing style, which specifies what type of communication (by

value, by reference, by name) the argument is passed to the routine.

Page 34: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

30 16 Named and Default Arguments

Forcing matching parameter names in routine prototypes with corresponding routine definitions is possible,1

but goes against a strong tradition in C programming. Alternatively, prototype definitions can be elim-2

inated by using a two-pass compilation, and implicitly creating header files for exports. The former is3

easy to do, while the latter is more complex.4

Furthermore, named arguments do not work well in a C

A

-style programming-languages because5

they potentially introduces a new criteria for type matching. For example, it is technically possible to6

disambiguate between these two overloaded definitions of f based on named arguments at the call site:7

int f( int i, int j );8

int f( int x, double y );9

10

f( j : 3, i : 4 ); // 1st f11

f( x : 7, y : 8.1 ); // 2nd f12

f( 4, 5 ); // ambiguous call13

However, named arguments compound routine resolution in conjunction with conversions:14

f( i : 3, 5.7 ); // ambiguous call ?15

Depending on the cost associated with named arguments, this call could be resolvable or ambiguous.16

Adding named argument into the routine resolution algorithm does not seem worth the complexity.17

Therefore, C

A

does not attempt to support named arguments.18

Default Arguments provide the ability to associate a default value with a parameter so it can be optionally19

specified in the argument list. For example, given the routine:20

void p( int x = 1, int y = 2, int z = 3 ) {...}21

the allowable positional calls are:22

p(); // rewrite⇒ p( 1, 2, 3 )23

p( 4 ); // rewrite⇒ p( 4, 2, 3 )24

p( 4, 4 ); // rewrite⇒ p( 4, 4, 3 )25

p( 4, 4, 4 ); // rewrite⇒ p( 4, 4, 4 )26

// empty arguments27

p( , 4, 4 ); // rewrite⇒ p( 1, 4, 4 )28

p( 4, , 4 ); // rewrite⇒ p( 4, 2, 4 )29

p( 4, 4, ); // rewrite⇒ p( 4, 4, 3 )30

p( 4, , ); // rewrite⇒ p( 4, 2, 3 )31

p( , 4, ); // rewrite⇒ p( 1, 4, 3 )32

p( , , 4 ); // rewrite⇒ p( 1, 2, 4 )33

p( , , ); // rewrite⇒ p( 1, 2, 3 )34

Here the missing arguments are inserted from the default values in the parameter list. The compiler35

rewrites missing default values into explicit positional arguments. The advantages of default values are:36

• Routines with a large number of parameters are often very generalized, giving a programmer a37

number of different options on how a computation is performed. For many of these kinds of routines,38

there are standard or default settings that work for the majority of computations. Without default39

values for parameters, a programmer is forced to specify these common values all the time, resulting40

in long argument lists that are error prone.41

• When a routine’s interface is augmented with new parameters, it extends the interface providing42

generalizability18 (somewhat like the generalization provided by inheritance for classes). That is, all43

existing calls are still valid, although the call must still be recompiled.44

18 “It should be possible for the implementor of an abstraction to increase its generality. So long as the modified abstraction is a

Page 35: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

16 Named and Default Arguments 31

The only disadvantage of default arguments is that unintentional omission of an argument may not result1

in a compiler-time error. Instead, a default value is used, which may not be the programmer’s intent.2

Default values may only appear in a prototype versus definition context:3

void p( int x, int y = 2, int z = 3 ); // prototype: allowed4

void p( int, int = 2, int = 3 ); // prototype: allowed5

void p( int x, int y = 2, int z = 3 ) {} // definition: not allowed6

The reason for this restriction is to allow separate compilation. Multiple prototypes with different default7

values is an error.8

Ellipse (“...”) arguments present problems when used with default arguments. The conflict occurs9

because both named and ellipse arguments must appear after positional arguments, giving two possibilities:10

p( /* positional */, ... , /* named */ );11

p( /* positional */, /* named */, ... );12

While it is possible to implement both approaches, the first possibly is more complex than the second, e.g.:13

p( int x, int y, int z, ... );14

p( 1, 4, 5, 6, z : 3, y : 2 ); // assume p( /* positional */, ... , /* named */ );15

p( 1, z : 3, y : 2, 4, 5, 6 ); // assume p( /* positional */, /* named */, ... );16

In the first call, it is necessary for the programmer to conceptually rewrite the call, changing named argu-17

ments into positional, before knowing where the ellipse arguments begin. Hence, this approach seems18

significantly more difficult, and hence, confusing and error prone. In the second call, the named arguments19

separate the positional and ellipse arguments, making it trivial to read the call.20

The problem is exacerbated with default arguments, e.g.:21

void p( int x, int y = 2, int z = 3... );22

p( 1, 4, 5, 6, z : 3 ); // assume p( /* positional */, ... , /* named */ );23

p( 1, z : 3, 4, 5, 6 ); // assume p( /* positional */, /* named */, ... );24

The first call is an error because arguments 4 and 5 are actually positional not ellipse arguments; therefore,25

argument 5 subsequently conflicts with the named argument z : 3. In the second call, the default value26

for y is implicitly inserted after argument 1 and the named arguments separate the positional and ellipse27

arguments, making it trivial to read the call. For these reasons, C

A

requires named arguments before ellipse28

arguments. Finally, while ellipse arguments are needed for a small set of existing C routines, like printf, the29

extended C

A

type system largely eliminates the need for ellipse arguments (see Section 24), making much30

of this discussion moot.31

Default arguments and overloading (see Section 24) are complementary. While in theory default argu-32

ments can be simulated with overloading, as in:33

default arguments overloading

void p( int x, int y = 2, int z = 3 ) {...} void p( int x, int y, int z ) {...}void p( int x ) { p( x, 2, 3 ); }

void p( int x, int y ) { p( x, y, 3 ); }

34

the number of required overloaded routines is linear in the number of default values, which is unacceptable35

growth. In general, overloading should only be used over default arguments if the body of the routine is36

significantly different. Furthermore, overloading cannot handle accessing default arguments in the middle37

of a positional list, via a missing argument, such as:38

generalization of the original, existing uses of the abstraction will not require change. It might be possible to modify an abstraction

in a manner which is not a generalization without affecting existing uses, but, without inspecting the modules in which the uses

occur, this possibility cannot be determined. This criterion precludes the addition of parameters, unless these parameters have

default or inferred values that are valid for all possible existing applications.” [10, p. 128]

Page 36: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

32 18.2 Routine Nesting

p( 1, /* default */, 5 ); // rewrite⇒ p( 1, 2, 5 )1

Given the C

A

restrictions above, both named and default arguments are backwards compatible. C++ only2

supports default arguments; Ada supports both named and default arguments.3

17 Unnamed Structure Fields4

C requires each field of a structure to have a name, except for a bit field associated with a basic type, e.g.:5

struct {6

int f1; // named field7

int f2 : 4; // named field with bit field size8

int : 3; // unnamed field for basic type with bit field size9

int ; // disallowed, unnamed field10

int *; // disallowed, unnamed field11

int (*)( int ); // disallowed, unnamed field12

};13

This requirement is relaxed by making the field name optional for all field declarations; therefore, all the14

field declarations in the example are allowed. As for unnamed bit fields, an unnamed field is used for15

padding a structure to a particular size. A list of unnamed fields is also supported, e.g.:16

struct {17

int , , ; // 3 unnamed fields18

}19

18 Nesting20

Nesting of types and routines is useful for controlling name visibility (name hiding).21

18.1 Type Nesting22

C

A

allows type nesting, and type qualification of the nested types (see Figure 4), where as C hoists (refactors)23

nested types into the enclosing scope and has no type qualification. In the left example in C, types C, U and24

T are implicitly hoisted outside of type S into the containing block scope. In the right example in C

A

, the25

types are not hoisted and accessed using the field-selection operator “.” for type qualification, as does Java,26

rather than the C++ type-selection operator “::”.27

18.2 Routine Nesting28

While C

A

does not provide object programming by putting routines into structures, it does rely heavily on29

locally nested routines to redefine operations at or close to a call site. For example, the C quick-sort is30

wrapped into the following polymorphic C

A

routine:31

forall( otype T | { int ?<?( T, T ); } )32

void qsort( const T * arr, size t dimension );33

which can be used to sort in ascending and descending order by locally redefining the less-than operator into34

greater-than.35

const unsigned int size = 5;36

int ia[size];37

... // assign values to array ia38

qsort( ia, size ); // sort ascending order using builtin ?<?39

{40

Page 37: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

19 Tuple 33

C Type Nesting C Implicit Hoisting C

A

struct S {enum C { R, G, B };

struct T {

union U { int i, j; };enum C c;

short int i, j;

};struct T t;

} s;

int fred() {

s.t.c = R;struct T t = { R, 1, 2 };

enum C c;

union U u;}

enum C { R, G, B };union U { int i, j; };

struct T {

enum C c;short int i, j;

};

struct S {struct T t;

} s;

struct S {enum C { R, G, B };

struct T {

union U { int i, j; };enum C c;

short int i, j;

};struct T t;

} s;

int fred() {

s.t.c = S.R; // type qualificationstruct S.T t = { S.R, 1, 2 };

enum S.C c;

union S.T.U u;}

Figure 4: Type Nesting / Qualification

int ?<?( int x, int y ) { return x > y; } // nested routine1

qsort( ia, size ); // sort descending order by local redefinition2

}3

Nested routines are not first-class, meaning a nested routine cannot be returned if it has references to4

variables in its enclosing blocks; the only exception is references to the external block of the translation unit,5

as these variables persist for the duration of the program. The following program in undefined in CA

(and6

Indexcgcc)7

[* [int]( int )] foo() { // int (* foo())( int )8

int i = 7;9

int bar( int p ) {10

i += 1; // dependent on local variable11

sout | i;12

}13

return bar; // undefined because of local dependence14

}15

int main() {16

* [int]( int ) fp = foo(); // int (* fp)( int )17

sout | fp( 3 );18

}19

because20

Currently, there are no lambda expressions, i.e., unnamed routines because routine names are very21

important to properly select the correct routine.22

19 Tuple23

In C and C

A

, lists of elements appear in several contexts, such as the parameter list of a routine call.24

f( 2, x, 3 + i ); // element list25

A list of elements is called a tuple, and is different from a comma expression.26

Page 38: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

34 19.1 Multiple-Return-Value Functions

19.1 Multiple-Return-Value Functions1

In C and most programming languages, functions return at most one value; however, many operations have2

multiple outcomes, some exceptional (see Section 11, p. 18). To emulate functions with multiple return3

values, aggregation and/or aliasing is used.4

In the former approach, a record type is created combining all of the return values. For example, consider5

C’s div function, which returns the quotient and remainder for a division of an integer value.6

typedef struct { int quot, rem; } div t; // from include stdlib.h7

div t div( int num, int den );8

div t qr = div( 13, 5 ); // return quotient/remainder aggregate9

printf( "%d %d\n", qr.quot, qr.rem ); // print quotient/remainder10

This approach requires a name for the return type and fields, where naming is a common programming-11

language issue. That is, naming creates an association that must be managed when reading and writing12

code. While effective when used sparingly, this approach does not scale when functions need to return13

multiple combinations of types.14

In the latter approach, additional return values are passed as pointer parameters. A pointer parameter is15

assigned inside the routine to emulate a return. For example, consider C’s modf function, which returns the16

integral and fractional part of a floating value.17

double modf( double x, double * i ); // from include math.h18

double intp, frac = modf( 13.5, &intp ); // return integral and fractional components19

printf( "%g %g\n", intp, frac ); // print integral/fractional components20

This approach requires allocating storage for the return values, which complicates the call site with a21

sequence of variable declarations leading to the call. Also, while a disciplined use of const can give clues22

about whether a pointer parameter is used as an out parameter, it is not obvious from the routine signature23

whether the callee expects such a parameter to be initialized before the call. Furthermore, while many C24

routines that accept pointers are safe for a NULL argument, there are many C routines that are not null-25

safe. Finally, C does not provide a mechanism to state that a parameter is going to be used as an additional26

return value, which makes the job of ensuring that a value is returned more difficult for the compiler. Still,27

not every routine with multiple return values should be required to return an error code, and error codes28

are easily ignored, so this is not a satisfying solution. As with the previous approach, this technique can29

simulate multiple return values, but in practice it is verbose and error prone.30

C

A

allows functions to return multiple values by extending the function declaration syntax. Multiple31

return values are declared as a comma-separated list of types in square brackets in the same location that the32

return type appears in standard C function declarations.33

[ char, int, double ] f( ... );34

The ability to return multiple values from a function requires a new syntax for the return statement. For35

consistency, the return statement in C

A

accepts a comma-separated list of expressions in square brackets.36

return [ c, i, d ];37

The expression resolution ensures the correct form is used depending on the values being returned and38

the return type of the current function. A multiple-returning function with return type T can return any39

expression that is implicitly convertible to T.40

A common use of a function’s output is input to another function. C

A

allows this case, without any new41

syntax; a multiple-returning function can be used in any of the contexts where an expression is allowed.42

When a function call is passed as an argument to another call, the best match of actual arguments to formal43

parameters is evaluated given all possible expression interpretations in the current scope.44

void g( int, int ); // 145

void g( double, double ); // 246

Page 39: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

19.2 Expressions 35

g( div( 13, 5 ) ); // select 11

g( modf( 13.5 ) ); // select 22

In this case, there are two overloaded g routines. Both calls to g expect two arguments that are matched3

by the two return values from div and modf. respectively, which are fed directly to the first and second4

parameters of g. As well, both calls to g have exact type matches for the two different versions of g, so these5

exact matches are chosen. When type matches are not exact, conversions are used to find a best match.6

The previous examples can be rewritten passing the multiple returned-values directly to the printf func-7

tion call.8

[ int, int ] div( int x, int y ); // from include stdlib9

printf( "%d %d\n", div( 13, 5 ) ); // print quotient/remainder10

11

[ double, double ] modf( double x ); // from include math12

printf( "%g %g\n", modf( 13.5 ) ); // print integral/fractional components13

This approach provides the benefits of compile-time checking for appropriate return statements as in aggre-14

gation, but without the required verbosity of declaring a new named type.15

Finally, the addition of multiple-return-value functions necessitates a syntax for retaining the multiple16

values at the call-site versus their temporary existence during a call. The simplest mechanism for retaining17

a return value in C is variable assignment. By assigning the multiple return-values into multiple variables,18

the values can be retrieved later. As such, C

A

allows assigning multiple values from a function into multiple19

variables, using a square-bracketed list of lvalue expressions on the left side.20

int quot, rem;21

[ quot, rem ] = div( 13, 5 ); // assign multiple variables22

printf( "%d %d\n", quot, rem ); // print quotient/remainder23

Here, the multiple return-values are matched in much the same way as passing multiple return-values to24

multiple parameters in a call.25

19.2 Expressions26

Multiple-return-value functions provide C

A

with a new syntax for expressing a combination of expressions27

in the return statement and a combination of types in a function signature. These notions are generalized28

to provide C

A

with tuple expressions and tuple types. A tuple expression is an expression producing a29

fixed-size, ordered list of values of heterogeneous types. The type of a tuple expression is the tuple of the30

subexpression types, or a tuple type.31

In C

A

, a tuple expression is denoted by a comma-separated list of expressions enclosed in square32

brackets. For example, the expression [5, 'x', 10.5] has type [int, char, double]. The previous expres-33

sion has 3 components. Each component in a tuple expression can be any C

A

expression, including another34

tuple expression. The order of evaluation of the components in a tuple expression is unspecified, to allow a35

compiler the greatest flexibility for program optimization. It is, however, guaranteed that each component of36

a tuple expression is evaluated for side-effects, even if the result is not used. Multiple-return-value functions37

can equivalently be called tuple-returning functions.38

19.3 Variables39

The previous call of div still requires the preallocation of multiple return-variables in a manner similar to the40

aliasing example. In C

A

, it is possible to overcome this restriction by declaring a tuple variable.41

[int, int] qr = div( 13, 5 ); // initialize tuple variable42

printf( "%d %d\n", qr ); // print quotient/remainder43

Page 40: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

36 19.5 Flattening and Structuring

It is now possible to match the multiple return-values to a single variable, in much the same way as aggre-1

gation. As well, the components of the tuple value are passed as separate parameters to printf, allowing2

direct printing of tuple variables. One way to access the individual components of a tuple variable is with3

assignment.4

[ quot, rem ] = qr; // assign multiple variables5

In addition to variables of tuple type, it is also possible to have pointers to tuples, and arrays of tuples.6

Tuple types can be composed of any types, except for array types, since array assignment is disallowed,7

which makes tuple assignment difficult when a tuple contains an array.8

[ double, int ] di;9

[ double, int ] * pdi10

[ double, int ] adi[10];11

This examples declares a variable of type [double, int], a variable of type pointer to [double, int], and an12

array of ten [double, int].13

19.4 Indexing14

It is also possible to access a single component of a tuple-valued expression without creating temporary15

variables. Given a tuple-valued expression enp and a compile-time constant integer i where 0≤ i < n, where16

n is the number of components in e, e.i accesses the i th component of e, e.g.:17

[int, double] x;18

[char *, int] f();19

void g(double, int);20

[int, double] * p;21

22

int y = x.0; // access int component of x23

y = f().1; // access int component of f24

p >0 = 5; // access int component of tuple pointed-to by p25

g( x.1, x.0 ); // rearrange x to pass to g26

double z = [ x, f() ].0.1; // access second component of first component of tuple expression27

Tuple-index expressions can occur on any tuple-typed expression, including tuple-returning functions, square-28

bracketed tuple expressions, and other tuple-index expressions, provided the retrieved component is also a29

tuple. This feature was proposed for K-W C but never implemented [29, p. 45].30

19.5 Flattening and Structuring31

As evident in previous examples, tuples in C

A

do not have a rigid structure. In function call contexts, tuples32

support implicit flattening and restructuring conversions. Tuple flattening recursively expands a tuple into33

the list of its basic components. Tuple structuring packages a list of expressions into a value of tuple type.34

int f(int, int);35

int g([int, int]);36

int h(int, [int, int]);37

[int, int] x;38

int y;39

40

f(x); // flatten41

g(y, 10); // structure42

h(x, y); // flatten & structure43

Page 41: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

19.6 Assignment 37

In C

A

, each of these calls is valid. In the call to f, x is implicitly flattened so that the components of x are1

passed as the two arguments to f. For the call to g, the values y and 10 are structured into a single argument2

of type [int, int] to match the type of the parameter of g. Finally, in the call to h, x is flattened to yield an3

argument list of length 3, of which the first component of x is passed as the first parameter of h, and the4

second component of x and y are structured into the second argument of type [int, int]. The flexible structure5

of tuples permits a simple and expressive function-call syntax to work seamlessly with both single- and6

multiple-return-value functions, and with any number of arguments of arbitrarily complex structure.7

In K-W C [5, 29], there were 4 tuple coercions: opening, closing, flattening, and structuring. Opening8

coerces a tuple value into a tuple of values, while closing converts a tuple of values into a single tuple value.9

Flattening coerces a nested tuple into a flat tuple, i.e., it takes a tuple with tuple components and expands it10

into a tuple with only non-tuple components. Structuring moves in the opposite direction, i.e., it takes a flat11

tuple value and provides structure by introducing nested tuple components.12

In C

A

, the design has been simplified to require only the two conversions previously described, which13

trigger only in function call and return situations. This simplification is a primary contribution of this thesis14

to the design of tuples in C

A

. Specifically, the expression resolution algorithm examines all of the possible15

alternatives for an expression to determine the best match. In resolving a function call expression, each16

combination of function value and list of argument alternatives is examined. Given a particular argument17

list and function value, the list of argument alternatives is flattened to produce a list of non-tuple valued18

expressions. Then the flattened list of expressions is compared with each value in the function’s parameter19

list. If the parameter’s type is not a tuple type, then the current argument value is unified with the parameter20

type, and on success the next argument and parameter are examined. If the parameter’s type is a tuple type,21

then the structuring conversion takes effect, recursively applying the parameter matching algorithm using22

the tuple’s component types as the parameter list types. Assuming a successful unification, eventually the23

algorithm gets to the end of the tuple type, which causes all of the matching expressions to be consumed24

and structured into a tuple expression. For example, in25

int f(int, [double, int]);26

f([5, 10.2], 4);27

There is only a single definition of f, and 3 arguments with only single interpretations. First, the argument28

alternative list [5, 10.2], 4 is flattened to produce the argument list 5, 10.2, 4. Next, the parameter matching29

algorithm begins, with P = int and A = int, which unifies exactly. Moving to the next parameter and argu-30

ment, P = [double, int] and A = double. This time, the parameter is a tuple type, so the algorithm applies31

recursively with P′ = double and A = double, which unifies exactly. Then P′ = int and A = double, which32

again unifies exactly. At this point, the end of P′ has been reached, so the arguments 10.2, 4 are structured33

into the tuple expression [10.2, 4]. Finally, the end of the parameter list P has also been reached, so the final34

expression is f(5, [10.2, 4]).35

19.6 Assignment36

An assignment where the left side of the assignment operator has a tuple type is called tuple assignment.37

There are two kinds of tuple assignment depending on whether the right side of the assignment operator has38

a non-tuple or tuple type, called mass and multiple assignment, respectively.39

int x;40

double y;41

[int, double] z;42

[y, x] = 3.14; // mass assignment43

[x, y] = z; // multiple assignment44

z = 10; // mass assignment45

z = [x, y]; // multiple assignment46

Page 42: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

38 19.6 Assignment

Let Li for i in [0,n) represent each component of the flattened left side, Ri represent each component of the1

flattened right side of a multiple assignment, and R represent the right side of a mass assignment.2

For a multiple assignment to be valid, both tuples must have the same number of elements when flat-3

tened. For example, the following is invalid because the number of components on the left does not match4

the number of components on the right.5

[ int, int ] x, y, z;6

[ x, y ] = z; // multiple assignment, invalid 4 != 27

Multiple assignment assigns Ri to Li for each i. That is, ?=?(&Li, Ri) must be a well-typed expression. In the8

previous example, [x, y] = z, z is flattened into z.0, z.1, and the assignments x = z.0 and y = z.1 happen.9

A mass assignment assigns the value R to each Li. For a mass assignment to be valid, ?=?(&Li, R)10

must be a well-typed expression. These semantics differ from C cascading assignment (e.g., a=b=c) in11

that conversions are applied to R in each individual assignment, which prevents data loss from the chain12

of conversions that can happen during a cascading assignment. For example, [y, x] = 3.14 performs the13

assignments y = 3.14 and x = 3.14, which results in the value 3.14 in y and the value 3 in x. On the other14

hand, the C cascading assignment y = x = 3.14 performs the assignments x = 3.14 and y = x, which results in15

the value 3 in x, and as a result the value 3 in y as well.16

Both kinds of tuple assignment have parallel semantics, such that each value on the left side and right17

side is evaluated before any assignments occur. As a result, it is possible to swap the values in two variables18

without explicitly creating any temporary variables or calling a function.19

int x = 10, y = 20;20

[ x, y ] = [ y, x ];21

After executing this code, x has the value 20 and y has the value 10.22

In C

A

, tuple assignment is an expression where the result type is the type of the left side of the assign-23

ment, as in normal assignment. That is, a tuple assignment produces the value of the left-hand side after24

assignment. These semantics allow cascading tuple assignment to work out naturally in any context where25

a tuple is permitted. These semantics are a change from the original tuple design in K-W C [29], wherein26

tuple assignment was a statement that allows cascading assignments as a special case. Restricting tuple27

assignment to statements was an attempt to to fix what was seen as a problem with side-effects, wherein28

assignment can be used in many different locations, such as in function-call argument position. While29

permitting assignment as an expression does introduce the potential for subtle complexities, it is impossible30

to remove assignment expressions from C

A

without affecting backwards compatibility. Furthermore, there31

are situations where permitting assignment as an expression improves readability by keeping code succinct32

and reducing repetition, and complicating the definition of tuple assignment puts a greater cognitive burden33

on the user. In another language, tuple assignment as a statement could be reasonable, but it would be incon-34

sistent for tuple assignment to be the only kind of assignment that is not an expression. In addition, K-W35

C permits the compiler to optimize tuple assignment as a block copy, since it does not support user-defined36

assignment operators. This optimization could be implemented in C

A

, but it requires the compiler to verify37

that the selected assignment operator is trivial.38

The following example shows multiple, mass, and cascading assignment used in one expression39

int a, b;40

double c, d;41

[ void ] f( [ int, int ] );42

f( [ c, a ] = [ b, d ] = 1.5 ); // assignments in parameter list43

The tuple expression begins with a mass assignment of 1.5 into [b, d], which assigns 1.5 into b, which is44

truncated to 1, and 1.5 into d, producing the tuple [1, 1.5] as a result. That tuple is used as the right side of45

the multiple assignment (i.e., [c, a] = [1, 1.5]) that assigns 1 into c and 1.5 into a, which is truncated to 1,46

producing the result [1, 1]. Finally, the tuple [1, 1] is used as an expression in the call to f.47

Page 43: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

19.7 Construction 39

19.7 Construction1

Tuple construction and destruction follow the same rules and semantics as tuple assignment, except that in2

the case where there is no right side, the default constructor or destructor is called on each component of the3

tuple. As constructors and destructors did not exist in previous versions of C

A

or in K-W C, this is a primary4

contribution of this thesis to the design of tuples.5

struct S;6

void ?{}(S *); // (1)7

void ?{}(S *, int); // (2)8

void ?{}(S * double); // (3)9

void ?{}(S *, S); // (4)10

11

[S, S] x = [3, 6.28]; // uses (2), (3), specialized constructors12

[S, S] y; // uses (1), (1), default constructor13

[S, S] z = x.0; // uses (4), (4), copy constructor14

In this example, x is initialized by the multiple constructor calls ?{}(&x.0, 3) and ?{}(&x.1, 6.28), while y is15

initialized by two default constructor calls ?{}(&y.0) and ?{}(&y.1). z is initialized by mass copy constructor16

calls ?{}(&z.0, x.0) and ?{}(&z.1, x.0). Finally, x, y, and z are destructed, i.e., the calls ∧?{}(&x.0), ∧?{}(&x.1),17

∧?{}(&y.0), ∧?{}(&y.1), ∧?{}(&z.0), and ∧?{}(&z.1).18

It is possible to define constructors and assignment functions for tuple types that provide new semantics,19

if the existing semantics do not fit the needs of an application. For example, the function void ?{}([T, U] *, S);20

can be defined to allow a tuple variable to be constructed from a value of type S.21

struct S { int x; double y; };22

void ?{}([int, double] * this, S s) {23

this >0 = s.x;24

this >1 = s.y;25

}26

Due to the structure of generated constructors, it is possible to pass a tuple to a generated constructor for a27

type with a member prefix that matches the type of the tuple. For example,28

struct S { int x; double y; int z };29

[int, double] t;30

S s = t;31

The initialization of s with t works by default because t is flattened into its components, which satisfies the32

generated field constructor ?{}(S *, int, double) to initialize the first two values.33

19.8 Member-Access Expression34

Tuples may be used to select multiple fields of a record by field name. The result is a single tuple-valued35

expression whose type is the tuple of the types of the members. For example,36

struct S { char x; int y; double z; } s;37

s.[x, y, z];38

Here, the type of s.[ x, y, z ] is [ char, int, double ]. A member tuple expression has the form e.[x, y, z]; where39

e is an expression with type T, where T supports member access expressions, and x, y, z are all members of40

T with types Tx, Ty, and Tz respectively. Then the type of e.[x, y, z] is [Tx, Ty, Tz].41

A member-access tuple may be used anywhere a tuple can be used, e.g.:42

s.[ y, z, x ] = [ 3, 3.2, 'x' ]; // equivalent to s.x = ’x’, s.y = 3, s.z = 3.243

f( s.[ y, z ] ); // equivalent to f( s.y, s.z )44

Page 44: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

40 19.9 Casting

Note, the fields appearing in a record-field tuple may be specified in any order; also, it is unnecessary to1

specify all the fields of a struct in a multiple record-field tuple.2

Since tuple-index expressions are a form of member-access expression, it is possible to use tuple-index3

expressions in conjunction with member-access expressions to restructure a tuple (e.g., rearrange compo-4

nents, drop components, duplicate components, etc.).5

[ int, int, long, double ] x;6

void f( double, long );7

8

f( x.[ 0, 3 ] ); // f( x.0, x.3 )9

x.[ 0, 1 ] = x.[ 1, 0 ]; // [ x.0, x.1 ] = [ x.1, x.0 ]10

[ long, int, long ] y = x.[ 2, 0, 2 ];11

It is possible for a member tuple expression to contain other member access expressions, e.g.:12

struct A { double i; int j; };13

struct B { int * k; short l; };14

struct C { int x; A y; B z; } v;15

v.[ x, y.[ i, j ], z.k ];16

This expression is equivalent to [ v.x, [ v.y.i, v.y.j ], v.z.k ]. That is, the aggregate expression is effectively17

distributed across the tuple allowing simple and easy access to multiple components in an aggregate without18

repetition. It is guaranteed that the aggregate expression to the left of the . in a member tuple expression is19

evaluated exactly once. As such, it is safe to use member tuple expressions on the result of a function with20

side-effects.21

[ int, float, double ] f();22

[ double, float ] x = f().[ 2, 1 ]; // f() called once23

In K-W C, member tuple expressions are known as record field tuples [29]. Since C

A

permits these tuple-24

access expressions using structures, unions, and tuples, member tuple expression or field tuple expression is25

more appropriate.26

19.9 Casting27

In C, the cast operator is used to explicitly convert between types. In C

A

, the cast operator has a secondary28

use, which is type ascription, since it forces the expression resolution algorithm to choose the lowest cost29

conversion to the target type. That is, a cast can be used to select the type of an expression when it is30

ambiguous, as in the call to an overloaded function.31

int f(); // (1)32

double f(); // (2)33

34

f(); // ambiguous - (1),(2) both equally viable35

(int)f(); // choose (2)36

Since casting is a fundamental operation in C

A

, casts need to be given a meaningful interpretation in the37

context of tuples. Taking a look at standard C provides some guidance with respect to the way casts should38

work with tuples.39

1 int f();40

2 void g();41

342

4 (void)f(); // valid, ignore results43

5 (int)g(); // invalid, void cannot be converted to int44

645

7 struct A { int x; };46

Page 45: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

19.10 Polymorphism 41

8 (struct A)f(); // invalid, int cannot be converted to A1

In C, line 4 is a valid cast, which calls f and discards its result. On the other hand, line 5 is invalid, because2

g does not produce a result, so requesting an int to materialize from nothing is nonsensical. Finally, line 8 is3

also invalid, because in C casts only provide conversion between scalar types [6, p. 91]. For consistency, this4

implies that any case wherein the number of components increases as a result of the cast is invalid, while5

casts that have the same or fewer number of components may be valid.6

Formally, a cast to tuple type is valid when Tn ≤ Sm, where Tn is the number of components in the target7

type and Sm is the number of components in the source type, and for each i in [0,n), Si can be cast to Ti.8

Excess elements (S j for all j in [n,m)) are evaluated, but their values are discarded so that they are not9

included in the result expression. This discarding naturally follows the way that a cast to void works in C.10

For example,11

[int, int, int] f();12

[int, [int, int], int] g();13

14

([int, double])f(); // (1) valid15

([int, int, int])g(); // (2) valid16

([void, [int, int]])g(); // (3) valid17

([int, int, int, int])g(); // (4) invalid18

([int, [int, int, int]])g(); // (5) invalid19

(1) discards the last element of the return value and converts the second element to type double. Since20

int is effectively a 1-element tuple, (2) discards the second component of the second element of the return21

value of g. If g is free of side effects, this is equivalent to [(int)(g().0), (int)(g().1.0), (int)(g().2)]. Since22

void is effectively a 0-element tuple, (3) discards the first and third return values, which is effectively23

equivalent to [(int)(g().1.0), (int)(g().1.1)]). Note that a cast is not a function call in C

A

, so flattening and24

structuring conversions do not occur for cast expressions. As such, (4) is invalid because the cast target25

type contains 4 components, while the source type contains only 3. Similarly, (5) is invalid because the cast26

([int, int, int])(g().1) is invalid. That is, it is invalid to cast [int, int] to [int, int, int].27

19.10 Polymorphism28

Due to the implicit flattening and structuring conversions involved in argument passing, otype and dtype29

parameters are restricted to matching only with non-tuple types. The integration of polymorphism, type30

assertions, and monomorphic specialization of tuple-assertions are a primary contribution of this thesis to31

the design of tuples.32

forall(otype T, dtype U)33

void f(T x, U * y);34

35

f([5, "hello"]);36

In this example, [5, "hello"] is flattened, so that the argument list appears as 5, "hello". The argument37

matching algorithm binds T to int and U to const char, and calls the function as normal.38

Tuples can contain otype and dtype components. For example, a plus operator can be written to add two39

triples of a type together.40

forall(otype T | { T ?+?(T, T); })41

[T, T, T] ?+?([T, T, T] x, [T, T, T] y) {42

return [x.0+y.0, x.1+y.1, x.2+y.2];43

}44

[int, int, int] x;45

int i1, i2, i3;46

Page 46: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

42 19.10 Polymorphism

[i1, i2, i3] = x + ([10, 20, 30]);1

Note that due to the implicit tuple conversions, this function is not restricted to the addition of two triples. A2

call to this plus operator type checks as long as a total of 6 non-tuple arguments are passed after flattening,3

and all of the arguments have a common type that can bind to T, with a pairwise ?+? over T. For example,4

these expressions also succeed and produce the same value.5

([x.0, x.1]) + ([x.2, 10, 20, 30]); // x + ([10, 20, 30])6

x.0 + ([x.1, x.2, 10, 20, 30]); // x + ([10, 20, 30])7

This presents a potential problem if structure is important, as these three expressions look like they should8

have different meanings. Furthermore, these calls can be made ambiguous by introducing seemingly different9

functions.10

forall(otype T | { T ?+?(T, T); })11

[T, T, T] ?+?([T, T] x, [T, T, T, T]);12

forall(otype T | { T ?+?(T, T); })13

[T, T, T] ?+?(T x, [T, T, T, T, T]);14

It is also important to note that these calls could be disambiguated if the function return types were different,15

as they likely would be for a reasonable implementation of ?+?, since the return type is used in overload16

resolution. Still, these semantics are a deficiency of the current argument matching algorithm, and depending17

on the function, differing return values may not always be appropriate. These issues could be rectified by18

applying an appropriate conversion cost to the structuring and flattening conversions, which are currently19

0-cost conversions in the expression resolver. Care would be needed in this case to ensure that exact matches20

do not incur such a cost.21

void f([int, int], int, int);22

23

f([0, 0], 0, 0); // no cost24

f(0, 0, 0, 0); // cost for structuring25

f([0, 0,], [0, 0]); // cost for flattening26

f([0, 0, 0], 0); // cost for flattening and structuring27

Until this point, it has been assumed that assertion arguments must match the parameter type exactly,28

modulo polymorphic specialization (i.e., no implicit conversions are applied to assertion arguments). This29

decision presents a conflict with the flexibility of tuples.30

19.10.1 Assertion Inference31

int f([int, double], double);32

forall(otype T, otype U | { T f(T, U, U); })33

void g(T, U);34

g(5, 10.21);35

If assertion arguments must match exactly, then the call to g cannot be resolved, since the expected type36

of f is flat, while the only f in scope requires a tuple type. Since tuples are fluid, this requirement reduces37

the usability of tuples in polymorphic code. To ease this pain point, function parameter and return lists38

are flattened for the purposes of type unification, which allows the previous example to pass expression39

resolution.40

This relaxation is made possible by extending the existing thunk generation scheme, as described by41

Bilson [2]. Now, whenever a candidate’s parameter structure does not exactly match the formal parameter’s42

structure, a thunk is generated to specialize calls to the actual function.43

int thunk(int p0, double p1, double p2) {44

return f([ p0, p1], p2);45

}46

Page 47: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

20 Tuples 43

Essentially, this provides flattening and structuring conversions to inferred functions, improving the compat-1

ibility of tuples and polymorphism.2

20 Tuples3

In C and C

A

, lists of elements appear in several contexts, such as the parameter list for a routine call. (More4

contexts are added shortly.) A list of such elements is called a lexical list. The general syntax of a lexical5

list is:6

[ exprlist ]7

where exprlist is a list of one or more expressions separated by commas. The brackets, [], allow differenti-8

ating between lexical lists and expressions containing the C comma operator. The following are examples9

of lexical lists:10

[ x, y, z ]11

[ 2 ]12

[ v+w, x*y, 3.14159, f() ]13

Tuples are permitted to contain sub-tuples (i.e., nesting), such as [ [ 14, 21 ], 9 ], which is a 2-element tuple14

whose first element is itself a tuple. Note, a tuple is not a record (structure); a record denotes a single value15

with substructure, whereas a tuple is multiple values with no substructure (see flattening coercion in Section16

12.1). In essence, tuples are largely a compile time phenomenon, having little or no runtime presence.17

Tuples can be organized into compile-time tuple variables; these variables are of tuple type. Tuple18

variables and types can be used anywhere lists of conventional variables and types can be used. The general19

syntax of a tuple type is:20

[ typelist ]21

where typelist is a list of one or more legal C

A

or C type specifications separated by commas, which may22

include other tuple type specifications. Examples of tuple types include:23

[ unsigned int, char ]24

[ double, double, double ]25

[ * int, int * ] // mix of CFA and ANSI26

[ * [ 5 ] int, * * char, * [ [ int, int ] ] (int, int) ]27

Like tuples, tuple types may be nested, such as [ [ int, int ], int ], which is a 2-element tuple type whose first28

element is itself a tuple type.29

Examples of declarations using tuple types are:30

[ int, int ] x; // 2 element tuple, each element of type int31

* [ char, char ] y; // pointer to a 2 element tuple32

[ [ int, int ] ] z ([ int, int ]);33

The last example declares an external routine that expects a 2 element tuple as an input parameter and returns34

a 2 element tuple as its result.35

As mentioned, tuples can appear in contexts requiring a list of value, such as an argument list of a36

routine call. In unambiguous situations, the tuple brackets may be omitted, e.g., a tuple that appears as an37

argument may have its square brackets omitted for convenience; therefore, the following routine invocations38

are equivalent:39

f( [ 1, x+2, fred() ] );40

f( 1, x+2, fred() );41

Also, a tuple or a tuple variable may be used to supply all or part of an argument list for a routine expecting42

multiple input parameters or for a routine expecting a tuple as an input parameter. For example, the following43

are all legal:44

[ int, int ] w1;45

Page 48: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

44 20.1 Tuple Coercions

[ int, int, int ] w2;1

[ void ] f (int, int, int); // three input parameters of type int2

[ void ] g ([ int, int, int ]); 3 element tuple as input3

f( [ 1, 2, 3 ] );4

f( w1, 3 );5

f( 1, w1 );6

f( w2 );7

g( [ 1, 2, 3 ] );8

g( w1, 3 );9

g( 1, w1 );10

g( w2 );11

Note, in all cases 3 arguments are supplied even though the syntax may appear to supply less than 3. As12

mentioned, a tuple does not have structure like a record; a tuple is simply converted into a list of components.13

✷ The present implementation of C

A

does not support nested routine calls when the inner routine14

returns multiple values; i.e., a statement such as g( f() ) is not supported. Using a temporary variable15

to store the results of the inner routine and then passing this variable to the outer routine works,16

however. ✷17

A tuple can contain a C comma expression, provided the expression containing the comma operator is18

enclosed in parentheses. For instance, the following tuples are equivalent:19

[ 1, 3, 5 ]20

[ 1, (2, 3), 5 ]21

The second element of the second tuple is the expression (2, 3), which yields the result 3. This requirement22

is the same as for comma expressions in argument lists.23

Type qualifiers, i.e., const and volatile, may modify a tuple type. The meaning is the same as for a type24

qualifier modifying an aggregate type [Int99, x 6.5.2.3(7),x 6.7.3(11)], i.e., the qualifier is distributed across25

all of the types in the tuple, e.g.:26

const volatile [ int, float, const int ] x;27

is equivalent to:28

[ const volatile int, const volatile float, const volatile int ] x;29

Declaration qualifiers can only appear at the start of a C

A

tuple declaration4, e.g.:30

extern [ int, int ] w1;31

static [ int, int, int ] w2;32

✷ Unfortunately, C’s syntax for subscripts precluded treating them as tuples. The C subscript list33

has the form [i][j]... and not [i, j, ...]. Therefore, there is no syntactic way for a routine returning34

multiple values to specify the different subscript values, e.g., f[ g() ] always means a single subscript35

value because there is only one set of brackets. Fixing this requires a major change to C because the36

syntactic form M[i, j, k] already has a particular meaning: i, j, k is a comma expression. ✷37

20.1 Tuple Coercions38

There are four coercions that can be performed on tuples and tuple variables: closing, opening, flattening39

and structuring. In addition, the coercion of dereferencing can be performed on a tuple variable to yield its40

value(s), as for other variables. A closing coercion takes a set of values and converts it into a tuple value,41

which is a contiguous set of values, as in:42

[ int, int, int, int ] w;43

w = [ 1, 2, 3, 4 ];44

Page 49: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

20.2 Mass Assignment 45

First the right-hand tuple is closed into a tuple value and then the tuple value is assigned.1

An opening coercion is the opposite of closing; a tuple value is converted into a tuple of values, as in:2

[ a, b, c, d ] = w3

w is implicitly opened to yield a tuple of four values, which are then assigned individually.4

A flattening coercion coerces a nested tuple, i.e., a tuple with one or more components, which are5

themselves tuples, into a flattened tuple, which is a tuple whose components are not tuples, as in:6

[ a, b, c, d ] = [ 1, [ 2, 3 ], 4 ];7

First the right-hand tuple is flattened and then the values are assigned individually. Flattening is also8

performed on tuple types. For example, the type [ int, [ int, int ], int ] can be coerced, using flattening, into9

the type [ int, int, int, int ].10

A structuring coercion is the opposite of flattening; a tuple is structured into a more complex nested11

tuple. For example, structuring the tuple [ 1, 2, 3, 4 ] into the tuple [ 1, [ 2, 3 ], 4 ] or the tuple type [ int, int, int, int ]12

into the tuple type [ int, [ int, int ], int ]. In the following example, the last assignment illustrates all the tuple13

coercions:14

[ int, int, int, int ] w = [ 1, 2, 3, 4 ];15

int x = 5;16

[ x, w ] = [ w, x ]; // all four tuple coercions17

Starting on the right-hand tuple in the last assignment statement, w is opened, producing a tuple of four18

values; therefore, the right-hand tuple is now the tuple [ [ 1, 2, 3, 4 ], 5 ]. This tuple is then flattened, yielding19

[ 1, 2, 3, 4, 5 ], which is structured into [ 1, [ 2, 3, 4, 5 ] ] to match the tuple type of the left-hand side. The20

tuple [ 2, 3, 4, 5 ] is then closed to create a tuple value. Finally, x is assigned 1 and w is assigned the tuple21

value using multiple assignment (see Section 14).22

✷ A possible additional language extension is to use the structuring coercion for tuples to initialize23

a complex record with a tuple. ✷24

20.2 Mass Assignment25

C

A

permits assignment to several variables at once using mass assignment [25]. Mass assignment has the26

following form:27

[ lvalue, ... , lvalue ] = expr ;28

The left-hand side is a tuple of lvalues, which is a list of expressions each yielding an address, i.e., any data29

object that can appear on the left-hand side of a conventional assignment statement. expr is any standard30

arithmetic expression. Clearly, the types of the entities being assigned must be type compatible with the31

value of the expression.32

Mass assignment has parallel semantics, e.g., the statement:33

[ x, y, z ] = 1.5;34

is equivalent to:35

x = 1.5; y = 1.5; z = 1.5;36

This semantics is not the same as the following in C:37

x = y = z = 1.5;38

as conversions between intermediate assignments may lose information. A more complex example is:39

[ i, y[i], z ] = a + b;40

which is equivalent to:41

t = a + b;42

Page 50: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

46 20.4 Cascade Assignment

a1 = &i; a2 = &y[i]; a3 = &z;1

*a1 = t; *a2 = t; *a3 = t;2

The temporary t is necessary to store the value of the expression to eliminate conversion issues. The tempo-3

raries for the addresses are needed so that locations on the left-hand side do not change as the values are4

assigned. In this case, y[i] uses the previous value of i and not the new value set at the beginning of the mass5

assignment.6

20.3 Multiple Assignment7

C

A

also supports the assignment of several values at once, known as multiple assignment [25, 18]. Multiple8

assignment has the following form:9

[ lvalue, ... , lvalue ] = [ expr , ... , expr ];10

The left-hand side is a tuple of lvalues, and the right-hand side is a tuple of exprs. Each expr appearing on11

the right-hand side of a multiple assignment statement is assigned to the corresponding lvalues on the left-12

hand side of the statement using parallel semantics for each assignment. An example of multiple assignment13

is:14

[ x, y, z ] = [ 1, 2, 3 ];15

Here, the values 1, 2 and 3 are assigned, respectively, to the variables x, y and z. A more complex example16

is:17

[ i, y[ i ], z ] = [ 1, i, a + b ];18

Here, the values 1, i and a + b are assigned to the variables i, y[i] and z, respectively. Note, the parallel19

semantics of multiple assignment ensures:20

[ x, y ] = [ y, x ];21

correctly interchanges (swaps) the values stored in x and y. The following cases are errors:22

[ a, b, c ] = [ 1, 2, 3, 4 ];23

[ a, b, c ] = [ 1, 2 ];24

because the number of entities in the left-hand tuple is unequal with the right-hand tuple.25

As for all tuple contexts in C, side effects should not be used because C does not define an ordering for26

the evaluation of the elements of a tuple; both these examples produce indeterminate results:27

f( x++, x++ ); // C routine call with side effects in arguments28

[ v1, v2 ] = [ x++, x++ ]; // side effects in righthand side of multiple assignment29

20.4 Cascade Assignment30

As in C, C

A

mass and multiple assignments can be cascaded, producing cascade assignment. Cascade31

assignment has the following form:32

tuple = tuple = ... = tuple;33

and it has the same parallel semantics as for mass and multiple assignment. Some examples of cascade34

assignment are:35

x1 = y1 = x2 = y2 = 0;36

[ x1, y1 ] = [ x2, y2 ] = [ x3, y3 ];37

[ x1, y1 ] = [ x2, y2 ] = 0;38

[ x1, y1 ] = z = 0;39

As in C, the rightmost assignment is performed first, i.e., assignment parses right to left.40

Page 51: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

21 Stream I/O Library 47

21 Stream I/O Library1

The goal of C

A

stream input/output (I/O) is to simplify the common cases, while fully supporting poly-2

morphism and user defined types in a consistent way. Stream I/O can be implicitly or explicitly formatted.3

Implicit formatting means C

A

selects the output or input format for values that match with the type of a4

variable. Explicit formatting means additional information is specified to augment how an output or input5

of value is interpreted. C

A

formatting is a cross between C printf and C++ cout manipulators, and Python6

implicit spacing and newline. Specifically:7

• printf/Python format codes are dense, making them difficult to read and remember. C

A

/C++ format8

manipulators are named, making them easier to read and remember.9

• printf/Python separates format codes from associated variables, making it difficult to match codes with10

variables. C

A

/C++ co-locate codes with associated variables, where C

A

has the tighter binding.11

• Format manipulators in C

A

have local effect, whereas C++ have global effect, except setw. Hence, it is12

common programming practice to toggle manipulators on and then back to the default to prevent down-13

stream side-effects. Without this programming style, errors occur when moving prints, as manipulator14

effects incorrectly flow into the new location. (To guarantee no side-effects, manipulator values must be15

saved and restored across function calls.)16

• C

A

has more sophisticated implicit spacing between values than Python, plus implicit newline at the end17

of a print.18

The C

A

header file for the I/O library is fstream.hfa.19

For implicit formatted output, the common case is printing a series of variables separated by whitespace.20

CA

C++ Python

int x = 1, y = 2, z = 3;sout | x | y | z; cout << x << " " << y << " " << z << endl;

x = 1; y = 2; z = 3print( x, y, z )

1 2 3 1 2 3 1 2 3

21

The C

A

form has half the characters of the C++ form, and is similar to Python I/O with respect to implicit22

separators and newline. Similar simplification occurs for tuple I/O, which flattens the tuple and prints each23

value separated by “, ”.24

[int, [ int, int ] ] t1 = [ 1, [ 2, 3 ] ], t2 = [ 4, [ 5, 6 ] ];25

sout | t1 | t2; // print tuples26

1, 2, 3 4, 5, 627

Finally, C

A

uses the logical-or operator for I/O as it is the lowest-priority overloadable operator, other than28

assignment. Therefore, fewer output expressions require parenthesis.29

C

A

: sout | x * 3 | y + 1 | z << 2 | x == y | (x | y) | (x || y) | (x > z ? 1 : 2);

C++: cout << x * 3 << y + 1 << (z << 2) << (x == y) << (x | y) << (x || y) << (x > z ? 1 : 2) << endl;

3 3 12 0 3 1 2

30

Input and output use a uniform operator, |, rather than separate operators, as in >> and << for C++. There is a31

weak similarity between the C

A

logical-or operator and the Shell pipe-operator for moving data, where data32

flows in the correct direction for input but the opposite direction for output.33

For implicit formatted input, the common case is reading a sequence of values separated by whitespace,34

where the type of an input constant must match with the type of the input variable.35

Page 52: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

48 21.2 Separation Manipulators

int x; double y char z;

C

A

C++ Python

sin | x | y | z; cin >> x >> y >> z; x = int(input()); y = float(input()); z = input();

1 2.5 A 1 2.5 A 12.5

A

1

21.1 Implicit Separator2

The implicit separator character (space/blank) is a separator not a terminator for output. The rules for3

implicitly adding the separator are:4

1. A separator does not appear at the start or end of a line.5

sout | 1 | 2 | 3;6

1 2 37

2. A separator does not appear before or after a character literal or variable.8

sout | '1' | '2' | '3';9

12310

3. A separator does not appear before or after a null (empty) C string, which is a local mechanism to11

disable insertion of the separator character.12

sout | 1 | "" | 2 | "" | 3;13

12314

4. A separator does not appear before a C string starting with the (extended) ASCII characters: ,.;!?)]}%¢»,15

where » is a closing citation mark.16

sout | 1 | ", x" | 2 | ". x" | 3 | "; x" | 4 | "! x" | 5 | "? x" | 6 | "% x"17

| 7 | "¢ x" | 8 | "» x" | 9 | ") x" | 10 | "] x" | 11 | "} x";18

1, x 2. x 3; x 4! x 5? x 6% x 7¢ x 8» x 9) x 10] x 11} x19

5. A separator does not appear after a C string ending with the (extended) ASCII characters: ([{=$£¥¡¿«,20

where ¡¿ are inverted opening exclamation and question marks, and « is an opening citation mark.21

sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x =" | 4 | "x $" | 5 | "x £" | 6 | "x ¥"22

| 7 | "x ¡" | 8 | "x ¿" | 9 | "x «" | 10;23

x (1 x [2 x {3 x =4 x $5 x £6 x ¥7 x ¡8 x ¿9 x «1024

6. A seperator does not appear before/after a C string starting/ending with the ASCII quote or whitespace25

characters: ‘'": \t\v\f\r\n26

sout | "x‘" | 1 | "‘x'" | 2 | "'x\"" | 3 | "\"x:" | 4 | ":x " | 5 | " x\t" | 6 | "\tx";27

x‘1‘x’2’x"3"x:4:x 5 x 6 x28

7. If a space is desired before or after one of the special string start/end characters, simply insert a space.29

sout | "x ( " | 1 | " ) x" | 2 | " , x" | 3 | " :x: " | 4;30

x ( 1 ) x 2 , x 3 :x: 431

21.2 Separation Manipulators32

The following manipulators control implicit output separation. The effect of these manipulators is global33

for an output stream (except sepOn and sepOff).34

Page 53: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

21.2 Separation Manipulators 49

1. sepSet and sep/sepGet set and get the separator string. The separator string can be at most 16 char-1

acters including the '\0' string terminator (15 printable characters).2

sepSet( sout, ", $" ); // set separator from " " to ", $"3

sout | 1 | 2 | 3 | " \"" | sep | "\"";4

1, $2, $3 ", $"5

sepSet( sout, " " ); // reset separator to " "6

sout | 1 | 2 | 3 | " \"" | sepGet( sout ) | "\"";7

1 2 3 " "8

sepGet can be used to store a separator and then restore it:9

char store[sepSize]; // sepSize is the maximum separator size10

strcpy( store, sepGet( sout ) ); // copy current separator11

sepSet( sout, "_" ); // change separator to underscore12

sout | 1 | 2 | 3;13

1 2 314

sepSet( sout, store ); // change separator back to original15

sout | 1 | 2 | 3;16

1 2 317

2. sepSetTuple and sepTuple/sepGetTuple get and set the tuple separator-string. The tuple separator-18

string can be at most 16 characters including the '\0' string terminator (15 printable characters).19

sepSetTuple( sout, " " ); // set tuple separator from ", " to " "20

sout | t1 | t2 | " \"" | sepTuple | "\"";21

1 2 3 4 5 6 " "22

sepSetTuple( sout, ", " ); // reset tuple separator to ", "23

sout | t1 | t2 | " \"" | sepGetTuple( sout ) | "\"";24

1, 2, 3 4, 5, 6 ", "25

As for sepGet, sepGetTuple can be use to store a tuple separator and then restore it.26

3. sepDisable and sepEnable toggle printing the separator.27

sout | sepDisable | 1 | 2 | 3; // turn off implicit separator28

12329

sout | sepEnable | 1 | 2 | 3; // turn on implicit separator30

1 2 331

4. sepOn and sepOff toggle printing the separator with respect to the next printed item, and then return32

to the global seperator setting.33

sout | 1 | sepOff | 2 | 3; // turn off implicit separator for the next item34

12 335

sout | sepDisable | 1 | sepOn | 2 | 3; // turn on implicit separator for the next item36

1 2337

The tuple separator also responses to being turned on and off.38

sout | t1 | sepOff | t2; // turn off implicit separator for the next item39

1, 2, 34, 5, 640

sepOn cannot be used to start/end a line with a separator because separators do not appear at the41

start/end of a line; use sep to accomplish this functionality.42

sout | sepOn | 1 | 2 | 3 | sepOn; // sepOn does nothing at start/end of line43

Page 54: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

50 21.4 Output Value Manipulators

1 2 31

sout | sep | 1 | 2 | 3 | sep ; // use sep to print separator at start/end of line2

1 2 33

21.3 Newline Manipulators4

The following manipulators control newline separation for input and output.5

For input:6

1. nl scans characters until the next newline character, i.e., ignore the remaining characters in the line.7

2. nlOn reads the newline character, when reading single characters.8

3. nlOff does not read the newline character, when reading single characters.9

For example, in:10

sin | i | nl | j;11

1 212

313

variable i is assigned 1, the 2 is skipped, and variable j is assigned 3.14

For output:15

1. nl inserts a newline.16

sout | nl; // only print newline17

sout | 2; // implicit newline18

sout | 3 | nl | 4 | nl; // terminating nl merged with implicit newline19

sout | 5 | nl | nl; // again terminating nl merged with implicit newline20

sout | 6; // implicit newline21

22

223

324

425

526

27

628

Note, a terminating nl is merged (overrides) with the implicit newline at the end of the sout expression,29

otherwise it is impossible to to print a single newline30

2. nlOn implicitly prints a newline at the end of each output expression.31

3. nlOff does not implicitly print a newline at the end of each output expression.32

21.4 Output Value Manipulators33

The following manipulators control formatting of output values (printing), and only affect the format of the34

argument.35

1. bin( integer ) print value in base 2 preceded by 0b/0B.36

sout | bin( 0 ) | bin( 27HH ) | bin( 27H ) | bin( 27 ) | bin( 27L );37

0b0 0b11011 0b11011 0b11011 0b1101138

sout | bin( 27HH ) | bin( 27H ) | bin( 27 ) | bin( 27L );39

0b11100101 0b1111111111100101 0b11111111111111111111111111100101 0b(58 1s)10010140

Page 55: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

21.4 Output Value Manipulators 51

2. oct( integer ) print value in base 8 preceded by 0.1

sout | oct( 0 ) | oct( 27HH ) | oct( 27H ) | oct( 27 ) | oct( 27L );2

0 033 033 033 0333

sout | oct( 27HH ) | oct( 27H ) | oct( 27 ) | oct( 27L );4

0345 0177745 037777777745 017777777777777777777455

Note, octal 0 is not preceded by 0 to prevent confusion.6

3. hex( integer / floating-point ) print value in base 16 preceded by 0x/0X.7

sout | hex( 0 ) | hex( 27HH ) | hex( 27H ) | hex( 27 ) | hex( 27L );8

0 0x1b 0x1b 0x1b 0x1b9

sout | hex( 27HH ) | hex( 27H ) | hex( 27 ) | hex( 27L );10

0xe5 0xffe5 0xffffffe5 0xffffffffffffffe511

12

sout | hex( 0.0 ) | hex( 27.5F ) | hex( 27.5 ) | hex( 27.5L );13

0x0.p+0 0x1.b8p+4 0x1.b8p+4 0xd.cp+114

sout | hex( 27.5F ) | hex( 27.5 ) | hex( 27.5L );15

0x1.b8p+4 0x1.b8p+4 0xd.cp+116

4. sci( floating-point ) print value in scientific notation with exponent. Default is 6 digits of precision.17

sout | sci( 0.0 ) | sci( 27.5 ) | sci( 27.5 );18

0.000000e+00 2.750000e+01 2.750000e+0119

5. upcase( bin / hex / floating-point ) print letters in a value in upper case. Lower case is the default.20

sout | upcase( bin( 27 ) ) | upcase( hex( 27 ) ) | upcase( 27.5e 10 ) | upcase( hex( 27.5 ) );21

0B11011 0X1B 2.75E 09 0X1.B8P+422

6. nobase( integer ) do not precede bin, oct, hex with 0b/0B, 0, or 0x/0X. Printing the base is the default.23

sout | nobase( bin( 27 ) ) | nobase( oct( 27 ) ) | nobase( hex( 27 ) );24

11011 33 1b25

7. nodp( floating-point ) do not print a decimal point if there are no fractional digits. Printing a decimal26

point is the default, if there are no fractional digits.27

sout | 0. | nodp( 0. ) | 27.0 | nodp( 27.0 ) | nodp( 27.5 );28

0.0 0 27.0 27 27.529

8. sign( integer / floating-point ) prefix with plus or minus sign (+ or ). Only printing the minus sign is30

the default.31

sout | sign( 27 ) | sign( 27 ) | sign( 27. ) | sign( 27. ) | sign( 27.5 ) | sign( 27.5 );32

+27 27 +27.0 27.0 +27.5 27.533

9. wd( unsigned char minimum, T val ), wd( unsigned char minimum, unsigned char precision, T val )34

For all types, minimum is the minimum number of printed characters. If the value is shorter than the35

minimum, it is padded on the right with spaces.36

sout | wd( 4, 34) | wd( 3, 34 ) | wd( 2, 34 );37

sout | wd( 10, 4.) | wd( 9, 4. ) | wd( 8, 4. );38

sout | wd( 4, "ab" ) | wd( 3, "ab" ) | wd( 2, "ab" );39

34 34 3440

4.000000 4.000000 4.00000041

ab ab ab42

If the value is larger, it is printed without truncation, ignoring the minimum.43

Page 56: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

52 21.4 Output Value Manipulators

sout | wd( 4, 34567 ) | wd( 3, 34567 ) | wd( 2, 34567 );1

sout | wd( 4, 3456. ) | wd( 3, 3456. ) | wd( 2, 3456. );2

sout | wd( 4, "abcde" ) | wd( 3, "abcde" ) | wd( 2,"abcde" );3

34567 34567 345674

3456. 3456. 3456.5

abcde abcde abcde6

For integer types, precision is the minimum number of printed digits. If the value is shorter, it is7

padded on the left with leading zeros.8

sout | wd( 4,3, 34 ) | wd( 8,4, 34 ) | wd( 10,10, 34 );9

034 0034 000000003410

If the value is larger, it is printed without truncation, ignoring the precision.11

sout | wd( 4,1, 3456 ) | wd( 8,2, 3456 ) | wd( 10,3, 3456 );12

3456 3456 345613

If precision is 0, nothing is printed for zero. If precision is greater than the minimum, it becomes the14

minimum.15

sout | wd( 4,0, 0 ) | wd( 3,10, 34 );16

000000003417

For floating-point types, precision is the minimum number of digits after the decimal point.18

sout | wd( 6,3, 27.5 ) | wd( 8,1, 27.5 ) | wd( 8,0, 27.5 ) | wd( 3,8, 27.5 );19

27.500 27.5 28. 27.5000000020

For the C-string type, precision is the maximum number of printed characters, so the string is truncared21

if it exceeds the maximum.22

sout | wd( 6,8, "abcd" ) | wd( 6,8, "abcdefghijk" ) | wd( 6,3, "abcd" );23

abcd abcdefgh abc24

10. ws( unsigned char minimum, unsigned char significant, floating point ) For floating-point type, minimum25

is the same as for manipulator wd, but significant is the maximum number of significant digits to be26

printed for both the integer and fractions (versus only the fraction for wd). If a value’s significant27

digits is greater than significant, the last significant digit is rounded up.28

sout | ws(6,6, 234.567) | ws(6,5, 234.567) | ws(6,4, 234.567) | ws(6,3, 234.567);29

234.567 234.57 234.6 23530

If a value’s magnitude is greater than significant, the value is printed in scientific notation with the31

specified number of significant digits.32

sout | ws(6,6, 234567.) | ws(6,5, 234567.) | ws(6,4, 234567.) | ws(6,3, 234567.);33

234567. 2.3457e+05 2.346e+05 2.35e+0534

If significant is greater than minimum, it defines the number of printed characters.35

sout | ws(3,6, 234567.) | ws(4,6, 234567.) | ws(5,6, 234567.) | ws(6,6, 234567.);36

234567. 234567. 234567. 234567.37

11. left( field-width ) left justify within the given field.38

sout | left(wd(4, 27)) | left(wd(10, 27.)) | left(wd(10, 27.5)) | left(wd(4,3, 27)) | left(wd(10,3, 27.5));39

27 27.000000 27.500000 027 27.50040

12. pad0( field-width ) left pad with zeroes (0).41

sout | pad0( wd( 4, 27 ) ) | pad0( wd( 4,3, 27 ) ) | pad0( wd( 8,3, 27.5 ) );42

0027 027 0027.50043

Page 57: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

21.5 Input Value Manipulators 53

21.5 Input Value Manipulators1

The format of numeric input values in the same as C constants without a trailing type suffix, as the input2

value-type is denoted by the input variable. For Bool type, the constants are true and false. For integral3

types, any number of digits, optionally preceded by a sign (+ or ), where a4

• 1-9 prefix introduces a decimal value (0-9),5

• 0 prefix introduces an octal value (0-7), and6

• 0x or 0X prefix introduces a hexadecimal value (0-f) with lower or upper case letters.7

For floating-point types, any number of decimal digits, optionally preceded by a sign (+ or ), optionally8

containing a decimal point, and optionally followed by an exponent, e or E, with signed (optional) decimal9

digits. Floating-point values can also be written in hexadecimal format preceded by 0x or 0X with hexadec-10

imal digits and exponent denoted by p or P.11

For the C-string type, the input values are not the same as C-string constants, i.e., double quotes brack-12

eting arbitrary text with escape sequences. Instead, the next sequence of non-whitespace characters are13

read, and the input sequence is terminated with delimiter '\0'. The string variable must be large enough to14

contain the input sequence.15

The following manipulators control formatting of input values (reading), and only affect the format of16

the argument.17

1. skip( const char * pattern ) / skip( unsigned int length ) / const char * pattern The argument defines18

a pattern or length. The pattern is composed of white-space and non-white-space characters, where19

any white-space character matches 0 or more input white-space characters (hence, consecutive white-20

space characters in the pattern are combined), and each non-white-space character matches exactly21

with an input character. The length is composed of the next N characters, including the newline22

character. If the match successes, the input characters are discarded, and input continues with the next23

character. If the match fails, the input characters are left unread.24

char sk[ ] = "abc";25

sin | "abc " | skip( sk ) | skip( 5 ); // match input sequence26

abc27

abc28

xx29

2. wdi( unsigned int maximum, T & val ) For all types except char, maximum is the maximum number30

of characters read for the current operation.31

char s[10]; int i; double d;32

sin | wdi( 4, s ) | wdi( 3, i ) | wdi( 8, d ); // c == "abcd", i == 123, d == 3.456E+233

abcd1233.456E+234

Note, input wdi cannot be overloaded with output wd because both have the same parameters but35

return different types. Currently, C

A

cannot distinguish between these two manipulators in the middle36

of an sout/sin expression based on return type.37

3. ignore( T & val ) For all types, the data is read from the stream depending on the argument type but38

ignored, i.e., it is not stored in the argument.39

double d;40

sin | ignore( d ); // d is unchanged41

75.35e 4 2542

4. incl( const char * scanset, char * s ) For the C-string type, the argument defines a scanset that matches43

any number of characters in the set. Matching characters are read into the C string and null terminated.44

Page 58: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

54 22.1 Type Definitions

char s[10];1

sin | incl( "abc", s );2

bcaxyz3

5. excl( const char * scanset, char * s ) For the C-string type, the argument defines a scanset that matches4

any number of characters not in the set. Non-matching characters are read into the C string and null5

terminated.6

char s[10];7

sin | excl( "abc", s );8

xyzbca9

22 Types10

22.1 Type Definitions11

C

A

allows users to define new types using the keyword type.12

// SensorValue is a distinct type and represented as an int13

type SensorValue = int;14

A type definition is different from a typedef in C because a typedef just creates an alias for a type, while15

Do.s type definition creates a distinct type. This means that users can define distinct function overloads for16

the new type (see Overloading for more information). For example:17

type SensorValue = int;18

void printValue(int v) {...}19

void printValue(SensorValue v) {...}20

void process(int v) {...}21

22

SensorValue s = ...;23

24

printValue(s); // calls version with SensorValue argument25

26

printValue((int) s); // calls version with int argument27

28

process(s); // implicit conversion to int29

If SensorValue was defined with a typedef, then these two print functions would not have unique signa-30

tures. This can be very useful to create a distinct type that has the same representation as another type.31

The compiler will assume it can safely convert from the old type to the new type, implicitly. Users may32

override this and define a function that must be called to convert from one type to another.33

type SensorValue = int;34

// ()? is the overloaded conversion operator identifier35

// This function converts an int to a SensorValue36

SensorValue ()?(int val) {37

...38

}39

void process(int v) {...}40

41

SensorValue s = ...;42

process(s); // implicit call to conversion operator43

In many cases, it is not desired for the compiler to do this implicit conversion. To avoid that, the user44

can use the explicit modifier on the conversion operator. Any places where the conversion is needed but not45

explicit (with a cast), will result in a compile-time error.46

Page 59: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

22.2 Structures 55

type SensorValue = int;1

2

// conversion from int to SensorValue; must be explicit3

explicit SensorValue ()?(int val) {4

...5

}6

7

void process(int v) {...}8

9

SensorValue s = ...;10

process(s); // implicit cast to int: compile time error11

process((int) s); // explicit cast to int: calls conversion func12

The conversion may not require any code, but still need to be explicit; in that case, the syntax can be13

simplified to:14

type SensorValue = int;15

explicit SensorValue ()?(int);16

void process(int v) {...}17

18

SensorValue s = ...;19

process(s); // compile time error20

process((int) s); // type is converted, no function is called21

22.2 Structures22

Structures in C

A

are basically the same as structures in C. A structure is defined with the same syntax as in23

C. When referring to a structure in C

A

, users may omit the struct keyword.24

struct Point {25

double x;26

double y;27

};28

29

Point p = {0.0, 0.0};30

C

A

does not support inheritance among types, but instead uses composition to enable reuse of structure31

fields. Composition is achieved by embedding one type into another. When type A is embedded in type B,32

an object with type B may be used as an object of type A, and the fields of type A are directly accessible.33

Embedding types is achieved using anonymous members. For example, using Point from above:34

void foo(Point p);35

36

struct ColoredPoint {37

Point; // anonymous member (no identifier)38

int Color;39

};40

...41

ColoredPoint cp = ...;42

cp.x = 10.3; // x from Point is accessed directly43

cp.color = 0x33aaff; // color is accessed normally44

foo(cp); // cp can be used directly as a Point45

Page 60: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

56 24.1 Overloaded Constant

23 Constructors and Destructors1

C

A

supports C initialization of structures, but it also adds constructors for more advanced initialization.2

Additionally, C

A

adds destructors that are called when a variable is deallocated (variable goes out of scope3

or object is deleted). These functions take a reference to the structure as a parameter (see References for4

more information).5

24 Overloading6

Overloading refers to the capability of a programmer to define and use multiple objects in a program with the7

same name. In C

A

, a declaration may overload declarations from outer scopes with the same name, instead8

of hiding them as is the case in C. This may cause identical C and C

A

programs to behave differently. The9

compiler selects the appropriate object (overload resolution) based on context information at the place where10

it is used. Overloading allows programmers to give functions with different signatures but similar semantics11

the same name, simplifying the interface to users. Disadvantages of overloading are that it can be used to12

give functions with different semantics the same name, causing confusion, or that the compiler may resolve13

to a different function from what the programmer expected. C

A

allows overloading of functions, operators,14

variables, and even the constants 0 and 1.15

The compiler follows some overload resolution rules to determine the best interpretation of all of these16

overloads. The best valid interpretations are the valid interpretations that use the fewest unsafe conversions.17

Of these, the best are those where the functions and objects involved are the least polymorphic. Of these, the18

best have the lowest total conversion cost, including all implicit conversions in the argument expressions.19

Of these, the best have the highest total conversion cost for the implicit conversions (if any) applied to the20

argument expressions. If there is no single best valid interpretation, or if the best valid interpretation is21

ambiguous, then the resulting interpretation is ambiguous. For details about type inference and overload22

resolution, please see the CA

Language Specification.23

int foo(int a, int b) {24

float sum = 0.0;25

float special = 1.0;26

{27

int sum = 0;28

// both the float and int versions of sum are available29

float special = 4.0;30

// this inner special hides the outer version31

...32

}33

...34

}35

24.1 Overloaded Constant36

The constants 0 and 1 have special meaning. In C

A

, as in C, all scalar types can be incremented and37

decremented, which is defined in terms of adding or subtracting 1. The operations &&, ||, and ! can be38

applied to any scalar arguments and are defined in terms of comparison against 0 (ex. (a && b) becomes39

(a != 0 && b != 0)).40

In C, the integer constants 0 and 1 suffice because the integer promotion rules can convert them to41

any arithmetic type, and the rules for pointer expressions treat constant expressions evaluating to 0 as a42

special case. However, user-defined arithmetic types often need the equivalent of a 1 or 0 for their functions43

or operators, polymorphic functions often need 0 and 1 constants of a type matching their polymorphic44

Page 61: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

24.1 Overloaded Constant 57

struct Widget {int id;

float size;Parts * optionalParts;

};

// ?{} is the constructor operator identifier

// The first argument is a reference to the type to initialize// Subsequent arguments can be specified for initialization

void ?{}(Widget &w) { // default constructorw.id = 1;

w.size = 0.0;

w.optionalParts = 0;}

// constructor with values (does not need to include all fields)

void ?{}(Widget &w, int id, float size) {

w.id = id;w.size = size;

w.optionalParts = 0;

}

// ∧? is the destructor operator identifiervoid ∧?(Widget &w) { // destructor

w.id = 0;

w.size = 0.0;if (w.optionalParts != 0) {

// This is the only pointer to optionalParts, free itfree(w.optionalParts);

w.optionalParts = 0;

}}

Widget baz; // reserve space onlyWidget foo{}; // calls default constructor

Widget bar{23, 2.45}; // calls constructor with valuesbaz{24, 0.91}; // calls constructor with values

?{}(baz, 24, 0.91}; // explicit call to constructor∧bar; // explicit call to destructor∧?(bar); // explicit call to destructor

Figure 5: Constructors and Destructors

Page 62: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

58 24.3 Function Overloading

parameters, and user-defined pointer-like types may need a null value. Defining special constants for a1

user-defined type is more efficient than defining a conversion to the type from Bool.2

Why just 0 and 1? Why not other integers? No other integers have special status in C. A facility3

that let programmers declare specific constants..const Rational 12., for instance. would not be much of an4

improvement. Some facility for defining the creation of values of programmer-defined types from arbitrary5

integer tokens would be needed. The complexity of such a feature does not seem worth the gain.6

For example, to define the constants for a complex type, the programmer would define the following:7

struct Complex {8

double real;9

double imaginary;10

}11

12

const Complex 0 = {0, 0};13

const Complex 1 = {1, 0};14

...15

16

Complex a = 0;17

...18

19

a++;20

...21

if (a) { // same as if (a == 0)22

...23

}24

24.2 Variable Overloading25

The overload rules of C

A

allow a programmer to define multiple variables with the same name, but different26

types. Allowing overloading of variable names enables programmers to use the same name across multiple27

types, simplifying naming conventions and is compatible with the other overloading that is allowed. For28

example, a developer may want to do the following:29

int pi = 3;30

float pi = 3.14;31

char pi = .p.;32

24.3 Function Overloading33

Overloaded functions in C

A

are resolved based on the number and type of arguments, type of return value,34

and the level of specialization required (specialized functions are preferred over generic).35

The examples below give some basic intuition about how the resolution works.36

// Choose the one with less conversions37

int doSomething(int value) {...} // option 138

int doSomething(short value) {...} // option 239

40

int a, b = 4;41

short c = 2;42

43

a = doSomething(b); // chooses option 144

a = doSomething(c); // chooses option 245

46

Page 63: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

24.4 Operator Overloading 59

// Choose the specialized version over the generic1

2

generic(type T)3

T bar(T rhs, T lhs) {...} // option 34

float bar(float rhs, float lhs){...} // option 45

float a, b, c;6

double d, e, f;7

c = bar(a, b); // chooses option 48

9

// specialization is preferred over unsafe conversions10

11

f = bar(d, e); // chooses option 512

24.4 Operator Overloading13

C

A

also allows operators to be overloaded, to simplify the use of user-defined types. Overloading the opera-14

tors allows the users to use the same syntax for their custom types that they use for built-in types, increasing15

readability and improving productivity. C

A

uses the following special identifiers to name overloaded opera-16

tors:17

?[?] subscripting

?() function call

?++ postfix increment

? postfix decrement

++? prefix increment

? prefix decrement

*? dereference

+? unary plus

? arithmetic negation∼? bitwise negation

!? logical complement

?\? exponentiation

?*? multiplication

?/? division

?%? remainder

?+? addition

? ? subtraction

?<<? left shift

?>>? right shift

?<? less than

?<=? less than or equal

?>=? greater than or equal

?>? greater than

?==? equality

?!=? inequality

?&? bitwise AND

?∧? exclusive OR

?|? inclusive OR

?=? simple assignment

?\=? exponentiation assignment

?*=? multiplication assignment

?/=? division assignment

?%=? remainder assignment

?+=? addition assignment

? =? subtraction assignment

?<<=? left-shift assignment

?>>=? right-shift assignment

?&=? bitwise AND assignment

?∧=? exclusive OR assignment

?|=? inclusive OR assignment

Table 1: Operator Identifiers

These identifiers are defined such that the question marks in the name identify the location of the18

operands. These operands represent the parameters to the functions, and define how the operands are mapped19

to the function call. For example, a + b becomes ?+?(a, b).20

In the example below, a new type, myComplex, is defined with an overloaded constructor, + operator,21

and string operator. These operators are called using the normal C syntax.22

type Complex = struct { // define a Complex type23

double real;24

double imag;25

}26

27

// Constructor with default values28

29

Page 64: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

60 25 Auto Type-Inferencing

void ?{}(Complex &c, double real = 0.0, double imag = 0.0) {1

c.real = real;2

c.imag = imag;3

}4

5

Complex ?+?(Complex lhs, Complex rhs) {6

Complex sum;7

sum.real = lhs.real + rhs.real;8

sum.imag = lhs.imag + rhs.imag;9

return sum;10

}11

12

String ()?(const Complex c) {13

// use the string conversions for the structure members14

return (String)c.real + . + . + (String)c.imag + .i.;15

}16

...17

18

Complex a, b, c = {1.0}; // constructor for c w/ default imag19

...20

c = a + b;21

print(.sum = . + c);22

25 Auto Type-Inferencing23

Auto type-inferencing occurs in a declaration where a variable’s type is inferred from its initialization ex-24

pression type.25

C++ gcc

auto j = 3.0 * 4;

int i;auto k = i;

#define expr 3.0 * i

typeof(expr) j = expr;

int i;typeof(i) k = i;

// use type of initialization expression

// use type of primary variable

26

The two important capabilities are:27

• not determining or writing long generic types,28

• ensuring secondary variables, related to a primary variable, always have the same type.29

In C

A

, typedef provides a mechanism to alias long type names with short ones, both globally and30

locally, but not eliminate the use of the short name. gcc provides typeof to declare a secondary variable31

from a primary variable. C

A

also relies heavily on the specification of the left-hand side of assignment for32

type inferencing, so in many cases it is crucial to specify the type of the left-hand side to select the correct33

type of the right-hand expression. Only for overloaded routines with the same return type is variable type-34

inferencing possible. Finally, auto presents the programming problem of tracking down a type when the35

type is actually needed. For example, given36

auto j = ...37

and the need to write a routine to compute using j38

void rtn( ... parm );39

rtn( j );40

A programmer must work backwards to determine the type of j’s initialization expression, reconstructing41

the possibly long generic type-name. In this situation, having the type name or a short alias is very useful.42

Page 65: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

26 Concurrency 61

There is also the conundrum in type inferencing of when to brand a type. That is, when is the type of1

the variable more important than the type of its initialization expression. For example, if a change is made2

in an initialization expression, it can cause cascading type changes and/or errors. At some point, a variable3

type needs to remain constant and the expression to be in error when it changes.4

Given typedef and typeof in C

A

, and the strong need to use the type of left-hand side in inferencing, auto5

type-inferencing is not supported at this time. Should a significant need arise, this feature can be revisited.6

26 Concurrency7

Concurrency support in C

A

is implemented on top of a highly efficient runtime system of light-weight, M:N,8

user level threads. The model integrates concurrency features into the language by making the structure type9

the core unit of concurrency. All communication occurs through method calls, where data is sent via method10

arguments, and received via the return value. This enables a very familiar interface to all programmers, even11

those with no parallel programming experience. It also allows the compiler to do static type checking of all12

communication, a very important safety feature. This controlled communication with type safety has some13

similarities with channels in Go, and can actually implement channels exactly, as well as create additional14

communication patterns that channels cannot. Mutex objects, monitors, are used to contain mutual exclusion15

within an object and synchronization across concurrent threads.16

26.1 Coroutine17

Coroutines are the precursor to tasks. Figure 6 shows a coroutine that computes the Fibonacci numbers.18

26.2 Monitors19

A monitor is a structure in C

A

which includes implicit locking of its fields. Users of a monitor interact with20

it just like any structure, but the compiler handles code as needed to ensure mutual exclusion. An example21

of the definition of a monitor is shown here:22

type Account = monitor {23

const unsigned long number; // account number24

float balance; // account balance25

};26

26.3 Tasks27

C

A

also provides a simple mechanism for creating and utilizing user level threads. A task provides mutual28

exclusion like a monitor, and also has its own execution state and a thread of control. Similar to a monitor,29

a task is defined like a structure:30

27 Language Comparisons31

C

A

is one of many languages that attempts to improve upon C. In developing C

A

, many other languages32

were consulted for ideas, constructs, and syntax. Therefore, it is important to show how these languages33

each compare with Do. In this section, C

A

is compared with what the writers of this document consider to34

be the closest competitors of Do: C++, Go, Rust, and D.35

Page 66: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

62 27.1 C++

#include <fstream>

#include <coroutine>

coroutine Fibonacci {

int fn; // used for communication};

void ?{}( Fibonacci * this ) {

this >fn = 0;}

void main( Fibonacci * this ) {

int fn1, fn2; // retained between resumesthis >fn = 0; // case 0

fn1 = this >fn;suspend(); // return to last resume

this >fn = 1; // case 1fn2 = fn1;

fn1 = this >fn;suspend(); // return to last resume

for ( ;; ) { // general casethis >fn = fn1 + fn2;

fn2 = fn1;

fn1 = this >fn;suspend(); // return to last resume

} // for}

int next( Fibonacci * this ) {

resume( this ); // transfer to last suspendreturn this >fn;

}

int main() {Fibonacci f1, f2;

for ( int i = 1; i <= 10; i += 1 ) {sout | next( &f1 ) | ' ' | next( &f2 );

} // for

}

Figure 6: Fibonacci Coroutine

27.1 C++1

C++ is a general-purpose programming language. It has imperative, object-oriented and generic program-2

ming features, while also providing facilities for low-level memory manipulation. (Wikipedia)3

The primary focus of C++ seems to be adding object-oriented programming to C, and this is the primary4

difference between C++ and Do. C++ uses classes to encapsulate data and the functions that operate on that5

data, and to hide the internal representation of the data. C

A

uses modules instead to perform these same tasks.6

Classes in C++ also enable inheritance among types. Instead of inheritance, C

A

embraces composition and7

interfaces to achieve the same goals with more flexibility. There are many studies and articles comparing8

inheritance and composition (or is-a versus has-a relationships), so we will not go into more detail here9

(Venners, 1998) (Pike, Go at Google: Language Design in the Service of Software Engineering , 2012).10

Page 67: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

27.1 C++ 63

#include <fstream>

#include <kernel>#include <monitor>

#include <thread>

monitor global t {

int value;

};

void ?{}(global t * this) {this >value = 0;

}

static global t global;

void increment3( global t * mutex this ) {

this >value += 1;

}void increment2( global t * mutex this ) {

increment3( this );

}void increment( global t * mutex this ) {

increment2( this );}

thread MyThread {};

void main( MyThread* this ) {

for(int i = 0; i < 1 000 000; i++) {increment( &global );

}}

int main(int argc, char* argv[]) {

processor p;{

MyThread f[4];}

sout | global.value;

}

Figure 7: Atomic-Counter Monitor

Figure 8: f:AtomicCounterMonitor

Page 68: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

64 27.1 C++

#include <fstream>

#include <kernel>

#include <stdlib>#include <thread>

thread First { signal once * lock; };

thread Second { signal once * lock; };

void ?{}( First * this, signal once* lock ) { this >lock = lock; }

void ?{}( Second * this, signal once* lock ) { this >lock = lock; }

void main( First * this ) {

for ( int i = 0; i < 10; i += 1 ) {sout | "First : Suspend No." | i + 1;

yield();

}signal( this >lock );

}

void main( Second * this ) {

wait( this >lock );for ( int i = 0; i < 10; i += 1 ) {

sout | "Second : Suspend No." | i + 1;

yield();}

}

int main( void ) {

signal once lock;sout | "User main begin";

{

processor p;{

First f = { &lock };Second s = { &lock };

}

}sout | "User main end";

}

Figure 9: Simple Tasks

Overloading in C

A

is very similar to overloading in C++, with the exception of the additional use, in1

C

A

, of the return type to differentiate between overloaded functions. References and exceptions in C

A

are2

heavily based on the same features from C++. The mechanism for interoperating with C code in C

A

is also3

borrowed from C++.4

Both C

A

and C++ provide generics, and the syntax is quite similar. The key difference between the two,5

is that in C++ templates are expanded at compile time for each type for which the template is instantiated,6

while in C

A

, function pointers are used to make the generic fully compilable. This means that a generic7

function can be defined in a compiled library, and still be used as expected from source.8

Page 69: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

27.2 Go 65

27.2 Go1

Go, also commonly referred to as golang, is a programming language developed at Google in 2007 [.]. It is a2

statically typed language with syntax loosely derived from that of C, adding garbage collection, type safety,3

some structural typing capabilities, additional built-in types such as variable-length arrays and key-value4

maps, and a large standard library. (Wikipedia)5

Go and C

A

differ significantly in syntax and implementation, but the underlying core concepts of the6

two languages are aligned. Both Go and C

A

use composition and interfaces as opposed to inheritance to7

enable encapsulation and abstraction. Both languages (along with their tooling ecosystem) provide a simple8

packaging mechanism for building units of code for easy sharing and reuse. Both languages also include9

built-in light weight, user level threading concurrency features that attempt to simplify the effort and thought10

process required for writing parallel programs while maintaining high performance.11

Go has a significant runtime which handles the scheduling of its light weight threads, and performs12

garbage collection, among other tasks. C

A

uses a cooperative scheduling algorithm for its tasks, and uses13

automatic reference counting to enable advanced memory management without garbage collection. This14

results in Go requiring significant overhead to interface with C libraries while C

A

has no overhead.15

27.3 Rust16

Rust is a general-purpose, multi-paradigm, compiled programming language developed by Mozilla Research.17

It is designed to be a "safe, concurrent, practical language", supporting pure-functional, concurrent-actor[dubious18

. discuss][citation needed], imperative-procedural, and object-oriented styles.19

The primary focus of Rust is in safety, especially in concurrent programs. To enforce a high level of20

safety, Rust has added ownership as a core feature of the language to guarantee memory safety. This safety21

comes at the cost of a difficult learning curve, a change in the thought model of the program, and often some22

runtime overhead.23

Aside from those key differences, Rust and C

A

also have several similarities. Both languages support24

no overhead interoperability with C and have minimal runtimes. Both languages support inheritance and25

polymorphism through the use of interfaces (traits).26

27.4 D27

The D programming language is an object-oriented, imperative, multi-paradigm system programming language28

created by Walter Bright of Digital Mars and released in 2001. [.] Though it originated as a re-engineering29

of C++, D is a distinct language, having redesigned some core C++ features while also taking inspiration from30

other languages, notably Java, Python, Ruby, C#, and Eiffel.31

D and C

A

both start with C and add productivity features. The obvious difference is that D uses classes32

and inheritance while C

A

uses composition and interfaces. D is closer to C

A

than C++ since it is limited33

to single inheritance and also supports interfaces. Like C++, and unlike C

A

, D uses garbage collection34

and has compile-time expanded templates. D does not have any built-in concurrency constructs in the35

language, though it does have a standard library for concurrency which includes the low-level primitives for36

concurrency.37

A Syntax Ambiguities38

C has a number of syntax ambiguities, which are resolved by taking the longest sequence of overlapping39

characters that constitute a token. For example, the program fragment x+++++y is parsed as x ++ ++ + y40

Page 70: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

66 B C Incompatibles

because operator tokens ++ and + overlap. Unfortunately, the longest sequence violates a constraint on incre-1

ment operators, even though the parse x ++ + ++ y might yield a correct expression. Hence, C program-2

mers are aware that spaces have to added to disambiguate certain syntactic cases.3

In C

A

, there are ambiguous cases with dereference and operator identifiers, e.g., int *?*?(), where the4

string *?*? can be interpreted as:5

*? *? // dereference operator, dereference operator6

* ?*? // dereference, multiplication operator7

By default, the first interpretation is selected, which does not yield a meaningful parse. Therefore, C

A

does a8

lexical look-ahead for the second case, and backtracks to return the leading unary operator and reparses the9

trailing operator identifier. Otherwise a space is needed between the unary operator and operator identifier10

to disambiguate this common case.11

A similar issue occurs with the dereference, *?(...), and routine-call, ?()(...) identifiers. The ambiguity12

occurs when the deference operator has no parameters:13

*?() ... ;14

*?() ...(...) ;15

requiring arbitrary whitespace look-ahead for the routine-call parameter-list to disambiguate. However, the16

dereference operator must have a parameter/argument to dereference *?(...). Hence, always interpreting the17

string *?() as * ?() does not preclude any meaningful program.18

The remaining cases are with the increment/decrement operators and conditional expression, e.g.:19

i++? ...(...);20

i?++ ...(...);21

requiring arbitrary whitespace look-ahead for the operator parameter-list, even though that interpretation is22

an incorrect expression (juxtaposed identifiers). Therefore, it is necessary to disambiguate these cases with23

a space:24

i++ ? i : 0;25

i? ++i : 0;26

B C Incompatibles27

The following incompatibles exist between C

A

and C, and are similar to Annex C for C++ [7].28

1. Change: add new keywords29

New keywords are added to C

A

(see Section C, p. 69).30

Rationale: keywords added to implement new semantics of C

A

.31

Effect on original feature: change to semantics of well-defined feature.32

Any C11 programs using these keywords as identifiers are invalid C

A

programs.33

Difficulty of converting: keyword clashes are accommodated by syntactic transformations using the34

C

A

backquote escape-mechanism (see Section 6, p. 5).35

How widely used: clashes among new C

A

keywords and existing identifiers are rare.36

2. Change: drop K&R C declarations37

K&R declarations allow an implicit base-type of int, if no type is specified, plus an alternate38

syntax for declaring parameters. e.g.:39

x; // int x40

*y; // int *y41

f( p1, p2 ); // int f( int p1, int p2 );42

g( p1, p2 ) int p1, p2; // int g( int p1, int p2 );43

Page 71: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

B C Incompatibles 67

C

A

continues to support K&R routine definitions:1

f( a, b, c ) // default int return2

int a, b; char c // K&R parameter declarations3

{4

...5

}6

Rationale: dropped from C11 standard.197

Effect on original feature: original feature is deprecated.8

Any old C programs using these K&R declarations are invalid C

A

programs.9

Difficulty of converting: trivial to convert to C

A

.10

How widely used: existing usages are rare.11

3. Change: type of character literal int to char to allow more intuitive overloading:12

int rtn( int i );13

int rtn( char c );14

rtn( 'x' ); // programmer expects 2nd rtn to be called15

Rationale: it is more intuitive for the call to rtn to match the second version of definition of rtn rather16

than the first. In particular, output of char variable now print a character rather than the decimal17

ASCII value of the character.18

sout | 'x' | " " | (int)'x';19

x 12020

Having to cast 'x' to char is non-intuitive.21

Effect on original feature: change to semantics of well-defined feature that depend on:22

sizeof( 'x' ) == sizeof( int )23

no long work the same in C

A

programs.24

Difficulty of converting: simple25

How widely used: programs that depend upon sizeof( 'x' ) are rare and can be changed to sizeof(char).26

4. Change: make string literals const:27

char * p = "abc"; // valid in C, deprecated in C

A

28

char * q = expr ? "abc" : "de"; // valid in C, invalid in C

A

29

The type of a string literal is changed from [] char to const [] char. Similarly, the type of a wide30

string literal is changed from [] wchar t to const [] wchar t.31

Rationale: This change is a safety issue:32

char * p = "abc";33

p[0] = 'w'; // segment fault or change constant literal34

The same problem occurs when passing a string literal to a routine that changes its argument.35

Effect on original feature: change to semantics of well-defined feature.36

Difficulty of converting: simple syntactic transformation, because string literals can be converted to37

char *.38

How widely used: programs that have a legitimate reason to treat string literals as pointers to poten-39

tially modifiable memory are rare.40

19 At least one type specifier shall be given in the declaration specifiers in each declaration, and in the specifier-qualifier list in each

structure declaration and type name [6, § 6.7.2(2)]

Page 72: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

68 B C Incompatibles

5. Change: remove tentative definitions, which only occurs at file scope:1

int i; // forward definition2

int *j = &i; // forward reference, valid in C, invalid in C

A

3

int i = 0; // definition4

is valid in C, and invalid in C

A

because duplicate overloaded object definitions at the same scope5

level are disallowed. This change makes it impossible to define mutually referential file-local6

static objects, if initializers are restricted to the syntactic forms of C. For example,7

struct X { int i; struct X *next; };8

static struct X a; // forward definition9

static struct X b = { 0, &a }; // forward reference, valid in C, invalid in C

A

10

static struct X a = { 1, &b }; // definition11

Rationale: avoids having different initialization rules for builtin types and user-defined types.12

Effect on original feature: change to semantics of well-defined feature.13

Difficulty of converting: the initializer for one of a set of mutually-referential file-local static objects14

must invoke a routine call to achieve the initialization.15

How widely used: seldom16

6. Change: have struct introduce a scope for nested types:17

enum Colour { R, G, B, Y, C, M };18

struct Person {19

enum Colour { R, G, B }; // nested type20

struct Face { // nested type21

Colour Eyes, Hair; // type defined outside (1 level)22

};23

.Colour shirt; // type defined outside (top level)24

Colour pants; // type defined same level25

Face looks[10]; // type defined same level26

};27

Colour c = R; // type/enum defined same level28

Person.Colour pc = Person.R; // type/enum defined inside29

Person.Face pretty; // type defined inside30

In C, the name of the nested types belongs to the same scope as the name of the outermost31

enclosing structure, i.e., the nested types are hoisted to the scope of the outer-most type, which32

is not useful and confusing. C

A

is C incompatible on this issue, and provides semantics similar33

to C++. Nested types are not hoisted and can be referenced using the field selection operator “.”,34

unlike the C++ scope-resolution operator “::”.35

Rationale: struct scope is crucial to C

A

as an information structuring and hiding mechanism.36

Effect on original feature: change to semantics of well-defined feature.37

Difficulty of converting: Semantic transformation.38

How widely used: C programs rarely have nest types because they are equivalent to the hoisted39

version.40

7. Change: In C++, the name of a nested class is local to its enclosing class.41

Rationale: C++ classes have member functions which require that classes establish scopes.42

Difficulty of converting: Semantic transformation. To make the struct type name visible in the scope43

of the enclosing struct, the struct tag could be declared in the scope of the enclosing struct, before44

the enclosing struct is defined. Example:45

Page 73: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

C C

A

Keywords 69

struct Y; // struct Y and struct X are at the same scope1

struct X {2

struct Y { /* ... */ } y;3

};4

All the definitions of C struct types enclosed in other struct definitions and accessed outside the5

scope of the enclosing struct could be exported to the scope of the enclosing struct. Note: this is6

a consequence of the difference in scope rules, which is documented in 3.3.7

How widely used: Seldom.8

8. Change: remove implicit conversion of void * to or from any T * pointer:9

void foo() {10

int * b = malloc( sizeof(int) ); // implicitly convert void * to int *11

char * c = b; // implicitly convert int * to void *, and then void * to char *12

}13

Rationale: increase type safety14

Effect on original feature: deletion of semantically well-defined feature.15

Difficulty of converting: requires adding a cast (see Section E.1 for better alternatives):16

int * b = (int *)malloc( sizeof(int) );17

char * c = (char *)b;18

How widely used: Significant. Some C translators already give a warning if the cast is not used.19

9. Change: Types must be declared in declarations, not in expressions In C, a sizeof expression or cast20

expression may create a new type. For example,21

p = (void*)(struct x {int i;} *)0;22

declares a new type, struct x .23

Rationale: This prohibition helps to clarify the location of declarations in the source code.24

Effect on original feature: Deletion of a semantically welldefined feature.25

Difficulty of converting: Syntactic transformation.26

How widely used: Seldom.27

10. Change: comma expression is disallowed as subscript28

Rationale: safety issue to prevent subscripting error for multidimensional arrays: x[i,j] instead of29

x[i][j], and this syntactic form then taken by C

A

for new style arrays.30

Effect on original feature: change to semantics of well-defined feature.31

Difficulty of converting: semantic transformation of x[i,j] to x[(i,j)]32

How widely used: Seldom.33

C C

A

Keywords34

C

A

introduces the following new keywords.35

catch

catchResume

choose

coroutine

disable

dtype

enable

exception

fallthrough

fallthru

finally

forall

ftype

monitor

mutex

one t

otype

throw

throwResume

trait

try

ttype

virtual

waitfor

when

with

zero t

36

Page 74: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

70 E.1 Storage Management

D Standard Headers1

C11 prescribes the following standard header-files [6, § 7.1.2] and C

A

adds to this list:2

C11 C

A

assert.h

complex.h

ctype.h

errno.h

fenv.h

float.h

inttypes.h

iso646.h

limits.h

locale.h

math.h

setjmp.h

signal.h

stdalign.h

stdarg.h

stdatomic.h

stdbool.h

stddef.h

stdint.h

stdio.h

stdlib.h

stdnoreturn.h

string.h

tgmath.h

threads.h

time.h

uchar.h

wchar.h

wctype.h

gmp.h

malloc.h

unistd.h3

For the prescribed head-files, C

A

uses header interposition to wraps these includes in an extern "C"; hence,4

names in these include files are not mangled (see Section 4, p. 3). All other C header files must be explicitly5

wrapped in extern "C" to prevent name mangling. This approach is different from C++ where the name-6

mangling issue is handled internally in C header-files through checks for preprocessor variable cplusplus,7

which adds appropriate extern "C" qualifiers.8

E Standard Library9

The C

A

standard-library wraps explicitly-polymorphic C routines into implicitly-polymorphic versions.10

E.1 Storage Management11

The storage-management routines extend their C equivalents by overloading, alternate names, providing12

shallow type-safety, and removing the need to specify the allocation size for non-array types.13

C storage management provides the following capabilities:14

filled after allocation with a specified character or value.15

resize an existing allocation to decreased or increased its size. In either case, new storage may or may not16

be allocated and, if there is a new allocation, as much data from the existing allocation is copied into the17

new allocation. For an increase in storage size, new storage after the copied data may be filled.18

align an allocation on a specified memory boundary, e.g., an address multiple of 64 or 128 for cache-line19

purposes.20

array the allocation size is scaled to the specified number of array elements. An array may be filled,21

resized, or aligned.22

Table 2 shows allocation routines supporting different combinations of storage-management capabilities:23

C

A

memory management extends the resize capability with the notion of sticky properties. Hence,24

initial allocation capabilities are remembered and maintained when resize requires copying. For example,25

an initial alignment and fill capability are preserved during a resize copy so the copy has the same alignment26

and extended storage is filled. Without sticky properties it is dangerous to use realloc, resulting in an idiom27

of manually performing the reallocation to maintain correctness.28

29

extern "C" {30

// C unsafe allocation31

void * malloc( size t size );32

void * calloc( size t dim, size t size );33

void * realloc( void * ptr, size t size );34

void * memalign( size t align, size t size );35

void * aligned alloc( size t align, size t size );36

int posix memalign( void ** ptr, size t align, size t size );37

Page 75: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

E.1 Storage Management 71

fill resize alignment array

C malloc no no no no

calloc yes (0 only) no no yes

realloc copy yes no no

memalign no no yes no

aligned alloc no no yes no

posix memalign no no yes no

C

A

cmemalign yes (0 only) no yes yes

realloc copy yes yes no

alloc no no no no

alloc copy no/yes no yes

alloc no/copy/yes no/yes no yes

alloc set no/yes no yes yes

alloc align no/yes no yes yes

alloc align set no/yes no yes yes

Table 2: Allocation Routines versus Storage-Management Capabilities

void * cmemalign( size t alignment, size t noOfElems, size t elemSize ); // CFA1

2

// C unsafe initialization/copy3

void * memset( void * dest, int c, size t size );4

void * memcpy( void * dest, const void * src, size t size );5

}6

7

void * realloc( void * oaddr, size t nalign, size t size ); // CFA heap8

9

forall( dtype T | sized(T) ) {10

// C

A

safe equivalents, i.e., implicit size specification11

T * malloc( void );12

T * calloc( size t dim );13

T * realloc( T * ptr, size t size );14

T * memalign( size t align );15

T * cmemalign( size t align, size t dim );16

T * aligned alloc( size t align );17

int posix memalign( T ** ptr, size t align );18

19

// C

A

safe general allocation, fill, resize, alignment, array20

T * alloc( void );21

T * alloc( size t dim );22

T * alloc( T ptr[], size t dim );23

T * alloc set( char fill );24

T * alloc set( T fill );25

T * alloc set( size t dim, char fill );26

T * alloc set( size t dim, T fill );27

T * alloc set( size t dim, const T fill[] );28

T * alloc set( T ptr[], size t dim, char fill );29

30

T * alloc align( size t align );31

T * alloc align( size t align, size t dim );32

T * alloc align( T ptr[], size t align ); // aligned realloc array33

Page 76: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

72 E.2 String to Value Conversion

T * alloc align( T ptr[], size t align, size t dim ); // aligned realloc array1

T * alloc align set( size t align, char fill );2

T * alloc align set( size t align, T fill );3

T * alloc align set( size t align, size t dim, char fill );4

T * alloc align set( size t align, size t dim, T fill );5

T * alloc align set( size t align, size t dim, const T fill[] );6

T * alloc align set( T ptr[], size t align, size t dim, char fill );7

8

// C

A

safe initialization/copy, i.e., implicit size specification9

T * memset( T * dest, char fill );10

T * memcpy( T * dest, const T * src );11

12

// C

A

safe initialization/copy, i.e., implicit size specification, array types13

T * amemset( T dest[], char fill, size t dim );14

T * amemcpy( T dest[], const T src[], size t dim );15

}16

17

// C

A

allocation/deallocation and constructor/destructor, non array types18

forall( dtype T | sized(T), ttype Params | { void ?{}( T &, Params ); } ) T * new( Params p );19

forall( dtype T | sized(T) | { void ∧?{}( T & ); } ) void delete( T * ptr );20

forall( dtype T, ttype Params | sized(T) | { void ∧?{}( T & ); void delete( Params ); } )21

void delete( T * ptr, Params rest );22

23

// C

A

allocation/deallocation and constructor/destructor, array types24

forall( dtype T | sized(T), ttype Params | { void ?{}( T &, Params ); } ) T * anew( size t dim, Params p );25

forall( dtype T | sized(T) | { void ∧?{}( T & ); } ) void adelete( size t dim, T arr[] );26

forall( dtype T | sized(T) | { void ∧?{}( T & ); }, ttype Params | { void adelete( Params ); } )27

void adelete( size t dim, T arr[], Params rest );28

E.2 String to Value Conversion29

int ato( const char * ptr );30

unsigned int ato( const char * ptr );31

long int ato( const char * ptr );32

unsigned long int ato( const char * ptr );33

long long int ato( const char * ptr );34

unsigned long long int ato( const char * ptr );35

float ato( const char * ptr );36

double ato( const char * ptr );37

long double ato( const char * ptr );38

float Complex ato( const char * ptr );39

double Complex ato( const char * ptr );40

long double Complex ato( const char * ptr );41

42

int strto( const char * sptr, char ** eptr, int base );43

unsigned int strto( const char * sptr, char ** eptr, int base );44

long int strto( const char * sptr, char ** eptr, int base );45

unsigned long int strto( const char * sptr, char ** eptr, int base );46

long long int strto( const char * sptr, char ** eptr, int base );47

unsigned long long int strto( const char * sptr, char ** eptr, int base );48

float strto( const char * sptr, char ** eptr );49

double strto( const char * sptr, char ** eptr );50

long double strto( const char * sptr, char ** eptr );51

Page 77: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

E.3 Search / Sort 73

float Complex strto( const char * sptr, char ** eptr );1

double Complex strto( const char * sptr, char ** eptr );2

long double Complex strto( const char * sptr, char ** eptr );3

E.3 Search / Sort4

forall( otype T | { int ?<?( T, T ); } ) // location5

T * bsearch( T key, const T * arr, size t dim );6

7

forall( otype T | { int ?<?( T, T ); } ) // position8

unsigned int bsearch( T key, const T * arr, size t dim );9

10

forall( otype T | { int ?<?( T, T ); } )11

void qsort( const T * arr, size t dim );12

13

forall( otype E | { int ?<?( E, E ); } ) {14

E * bsearch( E key, const E * vals, size t dim ); // location15

size t bsearch( E key, const E * vals, size t dim );// position16

E * bsearchl( E key, const E * vals, size t dim );17

size t bsearchl( E key, const E * vals, size t dim );18

E * bsearchu( E key, const E * vals, size t dim );19

size t bsearchu( E key, const E * vals, size t dim );20

}21

22

forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } ) {23

E * bsearch( K key, const E * vals, size t dim );24

size t bsearch( K key, const E * vals, size t dim );25

E * bsearchl( K key, const E * vals, size t dim );26

size t bsearchl( K key, const E * vals, size t dim );27

E * bsearchu( K key, const E * vals, size t dim );28

size t bsearchu( K key, const E * vals, size t dim );29

}30

31

forall( otype E | { int ?<?( E, E ); } ) {32

void qsort( E * vals, size t dim );33

}34

E.4 Absolute Value35

unsigned char abs( signed char );36

int abs( int );37

unsigned long int abs( long int );38

unsigned long long int abs( long long int );39

float abs( float );40

double abs( double );41

long double abs( long double );42

float abs( float Complex );43

double abs( double Complex );44

long double abs( long double Complex );45

forall( otype T | { void ?{}( T *, zero t ); int ?<?( T, T ); T ?( T ); } )46

T abs( T );47

Page 78: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

74 F.1 General

E.5 Random Numbers1

void srandom( unsigned int seed );2

char random( void );3

char random( char u ); // [0,u)4

char random( char l, char u ); // [l,u)5

int random( void );6

int random( int u ); // [0,u)7

int random( int l, int u ); // [l,u)8

unsigned int random( void );9

unsigned int random( unsigned int u ); // [0,u)10

unsigned int random( unsigned int l, unsigned int u ); // [l,u)11

long int random( void );12

long int random( long int u ); // [0,u)13

long int random( long int l, long int u ); // [l,u)14

unsigned long int random( void );15

unsigned long int random( unsigned long int u ); // [0,u)16

unsigned long int random( unsigned long int l, unsigned long int u ); // [l,u)17

float random( void ); // [0.0, 1.0)18

double random( void ); // [0.0, 1.0)19

float Complex random( void ); // [0.0, 1.0)+[0.0, 1.0)i20

double Complex random( void ); // [0.0, 1.0)+[0.0, 1.0)i21

long double Complex random( void ); // [0.0, 1.0)+[0.0, 1.0)i22

E.6 Algorithms23

forall( otype T | { int ?<?( T, T ); } ) T min( T t1, T t2 );24

forall( otype T | { int ?>?( T, T ); } ) T max( T t1, T t2 );25

forall( otype T | { T min( T, T ); T max( T, T ); } ) T clamp( T value, T min val, T max val );26

forall( otype T ) void swap( T * t1, T * t2 );27

F Math Library28

The C

A

math-library wraps explicitly-polymorphic C math-routines into implicitly-polymorphic versions.29

F.1 General30

float ?%?( float, float );31

float fmod( float, float );32

double ?%?( double, double );33

double fmod( double, double );34

long double ?%?( long double, long double );35

long double fmod( long double, long double );36

37

float remainder( float, float );38

double remainder( double, double );39

long double remainder( long double, long double );40

41

float remquo( float, float, int * );42

double remquo( double, double, int * );43

long double remquo( long double, long double, int * );44

[ int, float ] remquo( float, float );45

[ int, double ] remquo( double, double );46

Page 79: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

F.2 Exponential 75

[ int, long double ] remquo( long double, long double );1

2

float div( float, float, int * ); // alternative name for remquo3

double div( double, double, int * );4

long double div( long double, long double, int * );5

[ int, float ] div( float, float );6

[ int, double ] div( double, double );7

[ int, long double ] div( long double, long double );8

9

float fma( float, float, float );10

double fma( double, double, double );11

long double fma( long double, long double, long double );12

13

float fdim( float, float );14

double fdim( double, double );15

long double fdim( long double, long double );16

17

float nan( const char * );18

double nan( const char * );19

long double nan( const char * );20

F.2 Exponential21

float exp( float );22

double exp( double );23

long double exp( long double );24

float Complex exp( float Complex );25

double Complex exp( double Complex );26

long double Complex exp( long double Complex );27

28

float exp2( float );29

double exp2( double );30

long double exp2( long double );31

// float Complex exp2( float Complex );32

// double Complex exp2( double Complex );33

// long double Complex exp2( long double Complex );34

35

float expm1( float );36

double expm1( double );37

long double expm1( long double );38

39

float pow( float, float );40

double pow( double, double );41

long double pow( long double, long double );42

float Complex pow( float Complex, float Complex );43

double Complex pow( double Complex, double Complex );44

long double Complex pow( long double Complex, long double Complex );45

F.3 Logarithm46

float log( float );47

double log( double );48

long double log( long double );49

Page 80: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

76 F.4 Trigonometric

float Complex log( float Complex );1

double Complex log( double Complex );2

long double Complex log( long double Complex );3

4

float log2( float );5

double log2( double );6

long double log2( long double );7

// float Complex log2( float Complex );8

// double Complex log2( double Complex );9

// long double Complex log2( long double Complex );10

11

float log10( float );12

double log10( double );13

long double log10( long double );14

// float Complex log10( float Complex );15

// double Complex log10( double Complex );16

// long double Complex log10( long double Complex );17

18

float log1p( float );19

double log1p( double );20

long double log1p( long double );21

22

int ilogb( float );23

int ilogb( double );24

int ilogb( long double );25

26

float logb( float );27

double logb( double );28

long double logb( long double );29

30

float sqrt( float );31

double sqrt( double );32

long double sqrt( long double );33

float Complex sqrt( float Complex );34

double Complex sqrt( double Complex );35

long double Complex sqrt( long double Complex );36

37

float cbrt( float );38

double cbrt( double );39

long double cbrt( long double );40

41

float hypot( float, float );42

double hypot( double, double );43

long double hypot( long double, long double );44

F.4 Trigonometric45

float sin( float );46

double sin( double );47

long double sin( long double );48

float Complex sin( float Complex );49

double Complex sin( double Complex );50

long double Complex sin( long double Complex );51

Page 81: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

F.5 Hyperbolic 77

1

float cos( float );2

double cos( double );3

long double cos( long double );4

float Complex cos( float Complex );5

double Complex cos( double Complex );6

long double Complex cos( long double Complex );7

8

float tan( float );9

double tan( double );10

long double tan( long double );11

float Complex tan( float Complex );12

double Complex tan( double Complex );13

long double Complex tan( long double Complex );14

15

float asin( float );16

double asin( double );17

long double asin( long double );18

float Complex asin( float Complex );19

double Complex asin( double Complex );20

long double Complex asin( long double Complex );21

22

float acos( float );23

double acos( double );24

long double acos( long double );25

float Complex acos( float Complex );26

double Complex acos( double Complex );27

long double Complex acos( long double Complex );28

29

float atan( float );30

double atan( double );31

long double atan( long double );32

float Complex atan( float Complex );33

double Complex atan( double Complex );34

long double Complex atan( long double Complex );35

36

float atan2( float, float );37

double atan2( double, double );38

long double atan2( long double, long double );39

40

float atan( float, float ); // alternative name for atan241

double atan( double, double );42

long double atan( long double, long double );43

F.5 Hyperbolic44

float sinh( float );45

double sinh( double );46

long double sinh( long double );47

float Complex sinh( float Complex );48

double Complex sinh( double Complex );49

long double Complex sinh( long double Complex );50

51

Page 82: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

78 F.6 Error / Gamma

float cosh( float );1

double cosh( double );2

long double cosh( long double );3

float Complex cosh( float Complex );4

double Complex cosh( double Complex );5

long double Complex cosh( long double Complex );6

7

float tanh( float );8

double tanh( double );9

long double tanh( long double );10

float Complex tanh( float Complex );11

double Complex tanh( double Complex );12

long double Complex tanh( long double Complex );13

14

float asinh( float );15

double asinh( double );16

long double asinh( long double );17

float Complex asinh( float Complex );18

double Complex asinh( double Complex );19

long double Complex asinh( long double Complex );20

21

float acosh( float );22

double acosh( double );23

long double acosh( long double );24

float Complex acosh( float Complex );25

double Complex acosh( double Complex );26

long double Complex acosh( long double Complex );27

28

float atanh( float );29

double atanh( double );30

long double atanh( long double );31

float Complex atanh( float Complex );32

double Complex atanh( double Complex );33

long double Complex atanh( long double Complex );34

F.6 Error / Gamma35

float erf( float );36

double erf( double );37

long double erf( long double );38

float Complex erf( float Complex );39

double Complex erf( double Complex );40

long double Complex erf( long double Complex );41

42

float erfc( float );43

double erfc( double );44

long double erfc( long double );45

float Complex erfc( float Complex );46

double Complex erfc( double Complex );47

long double Complex erfc( long double Complex );48

49

float lgamma( float );50

double lgamma( double );51

Page 83: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

F.7 Nearest Integer 79

long double lgamma( long double );1

float lgamma( float, int * );2

double lgamma( double, int * );3

long double lgamma( long double, int * );4

5

float tgamma( float );6

double tgamma( double );7

long double tgamma( long double );8

F.7 Nearest Integer9

float floor( float );10

double floor( double );11

long double floor( long double );12

13

float ceil( float );14

double ceil( double );15

long double ceil( long double );16

17

float trunc( float );18

double trunc( double );19

long double trunc( long double );20

21

float rint( float );22

long double rint( long double );23

long int rint( float );24

long int rint( double );25

long int rint( long double );26

long long int rint( float );27

long long int rint( double );28

long long int rint( long double );29

30

long int lrint( float );31

long int lrint( double );32

long int lrint( long double );33

long long int llrint( float );34

long long int llrint( double );35

long long int llrint( long double );36

37

float nearbyint( float );38

double nearbyint( double );39

long double nearbyint( long double );40

41

float round( float );42

long double round( long double );43

long int round( float );44

long int round( double );45

long int round( long double );46

long long int round( float );47

long long int round( double );48

long long int round( long double );49

50

long int lround( float );51

Page 84: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

80 G.1 Duration

long int lround( double );1

long int lround( long double );2

long long int llround( float );3

long long int llround( double );4

long long int llround( long double );5

F.8 Manipulation6

float copysign( float, float );7

double copysign( double, double );8

long double copysign( long double, long double );9

10

float frexp( float, int * );11

double frexp( double, int * );12

long double frexp( long double, int * );13

14

float ldexp( float, int );15

double ldexp( double, int );16

long double ldexp( long double, int );17

18

[ float, float ] modf( float );19

float modf( float, float * );20

[ double, double ] modf( double );21

double modf( double, double * );22

[ long double, long double ] modf( long double );23

long double modf( long double, long double * );24

25

float nextafter( float, float );26

double nextafter( double, double );27

long double nextafter( long double, long double );28

29

float nexttoward( float, long double );30

double nexttoward( double, long double );31

long double nexttoward( long double, long double );32

33

float scalbn( float, int );34

double scalbn( double, int );35

long double scalbn( long double, int );36

37

float scalbln( float, long int );38

double scalbln( double, long int );39

long double scalbln( long double, long int );40

G Time Keeping41

G.1 Duration42

struct Duration {43

int64 t tv; // nanoseconds44

};45

46

void ?{}( Duration & dur );47

void ?{}( Duration & dur, zero t );48

Page 85: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

G.1 Duration 81

1

Duration ?=?( Duration & dur, zero t );2

3

Duration +?( Duration rhs );4

Duration ?+?( Duration & lhs, Duration rhs );5

Duration ?+=?( Duration & lhs, Duration rhs );6

7

Duration ?( Duration rhs );8

Duration ? ?( Duration & lhs, Duration rhs );9

Duration ? =?( Duration & lhs, Duration rhs );10

11

Duration ?*?( Duration lhs, int64 t rhs );12

Duration ?*?( int64 t lhs, Duration rhs );13

Duration ?*=?( Duration & lhs, int64 t rhs );14

15

int64 t ?/?( Duration lhs, Duration rhs );16

Duration ?/?( Duration lhs, int64 t rhs );17

Duration ?/=?( Duration & lhs, int64 t rhs );18

double div( Duration lhs, Duration rhs );19

20

Duration ?%?( Duration lhs, Duration rhs );21

Duration ?%=?( Duration & lhs, Duration rhs );22

23

Bool ?==?( Duration lhs, Duration rhs );24

Bool ?!=?( Duration lhs, Duration rhs );25

Bool ?<? ( Duration lhs, Duration rhs );26

Bool ?<=?( Duration lhs, Duration rhs );27

Bool ?>? ( Duration lhs, Duration rhs );28

Bool ?>=?( Duration lhs, Duration rhs );29

30

Bool ?==?( Duration lhs, zero t );31

Bool ?!=?( Duration lhs, zero t );32

Bool ?<? ( Duration lhs, zero t );33

Bool ?<=?( Duration lhs, zero t );34

Bool ?>? ( Duration lhs, zero t );35

Bool ?>=?( Duration lhs, zero t );36

37

Duration abs( Duration rhs );38

39

Duration ?‘ns( int64 t nsec );40

Duration ?‘us( int64 t usec );41

Duration ?‘ms( int64 t msec );42

Duration ?‘s( int64 t sec );43

Duration ?‘s( double sec );44

Duration ?‘m( int64 t min );45

Duration ?‘m( double min );46

Duration ?‘h( int64 t hours );47

Duration ?‘h( double hours );48

Duration ?‘d( int64 t days );49

Duration ?‘d( double days );50

Duration ?‘w( int64 t weeks );51

Duration ?‘w( double weeks );52

53

Page 86: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

82 G.5 Time

int64 t ?‘ns( Duration dur );1

int64 t ?‘us( Duration dur );2

int64 t ?‘ms( Duration dur );3

int64 t ?‘s( Duration dur );4

int64 t ?‘m( Duration dur );5

int64 t ?‘h( Duration dur );6

int64 t ?‘d( Duration dur );7

int64 t ?‘w( Duration dur );8

9

Duration max( Duration lhs, Duration rhs );10

Duration min( Duration lhs, Duration rhs );11

G.2 timeval12

void ?{}( timeval & t );13

void ?{}( timeval & t, time t sec, suseconds t usec );14

void ?{}( timeval & t, time t sec );15

void ?{}( timeval & t, zero t );16

void ?{}( timeval & t, Time time );17

18

timeval ?=?( timeval & t, zero t );19

timeval ?+?( timeval & lhs, timeval rhs );20

timeval ? ?( timeval & lhs, timeval rhs );21

Bool ?==?( timeval lhs, timeval rhs );22

Bool ?!=?( timeval lhs, timeval rhs );23

G.3 timespec24

void ?{}( timespec & t );25

void ?{}( timespec & t, time t sec, syscall slong t nsec );26

void ?{}( timespec & t, time t sec );27

void ?{}( timespec & t, zero t );28

void ?{}( timespec & t, Time time );29

30

timespec ?=?( timespec & t, zero t );31

timespec ?+?( timespec & lhs, timespec rhs );32

timespec ? ?( timespec & lhs, timespec rhs );33

Bool ?==?( timespec lhs, timespec rhs );34

Bool ?!=?( timespec lhs, timespec rhs );35

G.4 itimerval36

void ?{}( itimerval & itv, Duration alarm );37

void ?{}( itimerval & itv, Duration alarm, Duration interval );38

G.5 Time39

struct Time {40

uint64 t tv; // nanoseconds since UNIX epoch41

};42

43

void ?{}( Time & time );44

void ?{}( Time & time, zero t );45

Page 87: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

H Clock 83

1

Time ?=?( Time & time, zero t );2

3

void ?{}( Time & time, timeval t );4

Time ?=?( Time & time, timeval t );5

6

void ?{}( Time & time, timespec t );7

Time ?=?( Time & time, timespec t );8

9

Time ?+?( Time & lhs, Duration rhs );10

Time ?+?( Duration lhs, Time rhs );11

Time ?+=?( Time & lhs, Duration rhs );12

13

Duration ? ?( Time lhs, Time rhs );14

Time ? ?( Time lhs, Duration rhs );15

Time ? =?( Time & lhs, Duration rhs );16

Bool ?==?( Time lhs, Time rhs );17

Bool ?!=?( Time lhs, Time rhs );18

Bool ?<?( Time lhs, Time rhs );19

Bool ?<=?( Time lhs, Time rhs );20

Bool ?>?( Time lhs, Time rhs );21

Bool ?>=?( Time lhs, Time rhs );22

23

char * yy mm dd( Time time, char * buf );24

char * ?‘ymd( Time time, char * buf ) { // short form25

return yy mm dd( time, buf );26

} // ymd27

28

char * mm dd yy( Time time, char * buf );29

char * ?‘mdy( Time time, char * buf ) { // short form30

return mm dd yy( time, buf );31

} // mdy32

33

char * dd mm yy( Time time, char * buf );34

char * ?‘dmy( Time time, char * buf ) { // short form35

return dd mm yy( time, buf );;36

} // dmy37

38

size t strftime( char * buf, size t size, const char * fmt, Time time );39

forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype & os, Time time );40

H Clock41

H.1 C time42

char * ctime( time t tp );43

char * ctime r( time t tp, char * buf );44

tm * gmtime( time t tp );45

tm * gmtime r( time t tp, tm * result );46

tm * localtime( time t tp );47

tm * localtime r( time t tp, tm * result );48

Page 88: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

84 I Multi-precision Integers

H.2 Clock1

struct Clock {2

Duration offset; // for virtual clock: contains offset from real-time3

int clocktype; // implementation only -1 (virtual), CLOCK REALTIME4

};5

6

void resetClock( Clock & clk );7

void resetClock( Clock & clk, Duration adj );8

void ?{}( Clock & clk );9

void ?{}( Clock & clk, Duration adj );10

11

Duration getResNsec(); // with nanoseconds12

Duration getRes(); // without nanoseconds13

14

Time getTimeNsec(); // with nanoseconds15

Time getTime(); // without nanoseconds16

Time getTime( Clock & clk );17

Time ?()( Clock & clk );18

timeval getTime( Clock & clk );19

tm getTime( Clock & clk );20

I Multi-precision Integers21

C

A

has an interface to the GMP multi-precision signed-integers [19], similar to the C++ interface provided22

by GMP. The C

A

interface wraps GMP routines into operator routines to make programming with multi-23

precision integers identical to using fixed-sized integers. The CA

type name for multi-precision signed-24

integers is Int and the header file is gmp.25

void ?{}( Int * this ); // constructor/destructor26

void ?{}( Int * this, Int init );27

void ?{}( Int * this, zero t );28

void ?{}( Int * this, one t );29

void ?{}( Int * this, signed long int init );30

void ?{}( Int * this, unsigned long int init );31

void ?{}( Int * this, const char * val );32

void ∧?{}( Int * this );33

34

Int ?=?( Int * lhs, Int rhs ); // assignment35

Int ?=?( Int * lhs, long int rhs );36

Int ?=?( Int * lhs, unsigned long int rhs );37

Int ?=?( Int * lhs, const char * rhs );38

39

char ?=?( char * lhs, Int rhs );40

short int ?=?( short int * lhs, Int rhs );41

int ?=?( int * lhs, Int rhs );42

long int ?=?( long int * lhs, Int rhs );43

unsigned char ?=?( unsigned char * lhs, Int rhs );44

unsigned short int ?=?( unsigned short int * lhs, Int rhs );45

unsigned int ?=?( unsigned int * lhs, Int rhs );46

unsigned long int ?=?( unsigned long int * lhs, Int rhs );47

48

long int narrow( Int val );49

Page 89: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

I Multi-precision Integers 85

unsigned long int narrow( Int val );1

2

int ?==?( Int oper1, Int oper2 ); // comparison3

int ?==?( Int oper1, long int oper2 );4

int ?==?( long int oper2, Int oper1 );5

int ?==?( Int oper1, unsigned long int oper2 );6

int ?==?( unsigned long int oper2, Int oper1 );7

8

int ?!=?( Int oper1, Int oper2 );9

int ?!=?( Int oper1, long int oper2 );10

int ?!=?( long int oper1, Int oper2 );11

int ?!=?( Int oper1, unsigned long int oper2 );12

int ?!=?( unsigned long int oper1, Int oper2 );13

14

int ?<?( Int oper1, Int oper2 );15

int ?<?( Int oper1, long int oper2 );16

int ?<?( long int oper2, Int oper1 );17

int ?<?( Int oper1, unsigned long int oper2 );18

int ?<?( unsigned long int oper2, Int oper1 );19

20

int ?<=?( Int oper1, Int oper2 );21

int ?<=?( Int oper1, long int oper2 );22

int ?<=?( long int oper2, Int oper1 );23

int ?<=?( Int oper1, unsigned long int oper2 );24

int ?<=?( unsigned long int oper2, Int oper1 );25

26

int ?>?( Int oper1, Int oper2 );27

int ?>?( Int oper1, long int oper2 );28

int ?>?( long int oper1, Int oper2 );29

int ?>?( Int oper1, unsigned long int oper2 );30

int ?>?( unsigned long int oper1, Int oper2 );31

32

int ?>=?( Int oper1, Int oper2 );33

int ?>=?( Int oper1, long int oper2 );34

int ?>=?( long int oper1, Int oper2 );35

int ?>=?( Int oper1, unsigned long int oper2 );36

int ?>=?( unsigned long int oper1, Int oper2 );37

38

Int +?( Int oper ); // arithmetic39

Int ?( Int oper );40

Int ∼?( Int oper );41

42

Int ?&?( Int oper1, Int oper2 );43

Int ?&?( Int oper1, long int oper2 );44

Int ?&?( long int oper1, Int oper2 );45

Int ?&?( Int oper1, unsigned long int oper2 );46

Int ?&?( unsigned long int oper1, Int oper2 );47

Int ?&=?( Int * lhs, Int rhs );48

49

Int ?|?( Int oper1, Int oper2 );50

Int ?|?( Int oper1, long int oper2 );51

Int ?|?( long int oper1, Int oper2 );52

Int ?|?( Int oper1, unsigned long int oper2 );53

Page 90: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

86 I Multi-precision Integers

Int ?|?( unsigned long int oper1, Int oper2 );1

Int ?|=?( Int * lhs, Int rhs );2

3

Int ?∧?( Int oper1, Int oper2 );4

Int ?∧?( Int oper1, long int oper2 );5

Int ?∧?( long int oper1, Int oper2 );6

Int ?∧?( Int oper1, unsigned long int oper2 );7

Int ?∧?( unsigned long int oper1, Int oper2 );8

Int ?∧=?( Int * lhs, Int rhs );9

10

Int ?+?( Int addend1, Int addend2 );11

Int ?+?( Int addend1, long int addend2 );12

Int ?+?( long int addend2, Int addend1 );13

Int ?+?( Int addend1, unsigned long int addend2 );14

Int ?+?( unsigned long int addend2, Int addend1 );15

Int ?+=?( Int * lhs, Int rhs );16

Int ?+=?( Int * lhs, long int rhs );17

Int ?+=?( Int * lhs, unsigned long int rhs );18

Int ++?( Int * lhs );19

Int ?++( Int * lhs );20

21

Int ? ?( Int minuend, Int subtrahend );22

Int ? ?( Int minuend, long int subtrahend );23

Int ? ?( long int minuend, Int subtrahend );24

Int ? ?( Int minuend, unsigned long int subtrahend );25

Int ? ?( unsigned long int minuend, Int subtrahend );26

Int ? =?( Int * lhs, Int rhs );27

Int ? =?( Int * lhs, long int rhs );28

Int ? =?( Int * lhs, unsigned long int rhs );29

Int ?( Int * lhs );30

Int ? ( Int * lhs );31

32

Int ?*?( Int multiplicator, Int multiplicand );33

Int ?*?( Int multiplicator, long int multiplicand );34

Int ?*?( long int multiplicand, Int multiplicator );35

Int ?*?( Int multiplicator, unsigned long int multiplicand );36

Int ?*?( unsigned long int multiplicand, Int multiplicator );37

Int ?*=?( Int * lhs, Int rhs );38

Int ?*=?( Int * lhs, long int rhs );39

Int ?*=?( Int * lhs, unsigned long int rhs );40

41

Int ?/?( Int dividend, Int divisor );42

Int ?/?( Int dividend, unsigned long int divisor );43

Int ?/?( unsigned long int dividend, Int divisor );44

Int ?/?( Int dividend, long int divisor );45

Int ?/?( long int dividend, Int divisor );46

Int ?/=?( Int * lhs, Int rhs );47

Int ?/=?( Int * lhs, long int rhs );48

Int ?/=?( Int * lhs, unsigned long int rhs );49

50

[ Int, Int ] div( Int dividend, Int divisor );51

[ Int, Int ] div( Int dividend, unsigned long int divisor );52

53

Page 91: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

J Rational Numbers 87

Int ?%?( Int dividend, Int divisor );1

Int ?%?( Int dividend, unsigned long int divisor );2

Int ?%?( unsigned long int dividend, Int divisor );3

Int ?%?( Int dividend, long int divisor );4

Int ?%?( long int dividend, Int divisor );5

Int ?%=?( Int * lhs, Int rhs );6

Int ?%=?( Int * lhs, long int rhs );7

Int ?%=?( Int * lhs, unsigned long int rhs );8

9

Int ?<<?( Int shiften, mp bitcnt t shift );10

Int ?<<=?( Int * lhs, mp bitcnt t shift );11

Int ?>>?( Int shiften, mp bitcnt t shift );12

Int ?>>=?( Int * lhs, mp bitcnt t shift );13

14

Int abs( Int oper ); // number functions15

Int fact( unsigned long int N );16

Int gcd( Int oper1, Int oper2 );17

Int pow( Int base, unsigned long int exponent );18

Int pow( unsigned long int base, unsigned long int exponent );19

void srandom( gmp randstate t state );20

Int random( gmp randstate t state, mp bitcnt t n );21

Int random( gmp randstate t state, Int n );22

Int random( gmp randstate t state, mp size t max size );23

int sgn( Int oper );24

Int sqrt( Int oper );25

26

forall( dtype istype | istream( istype ) ) istype * ?|?( istype * is, Int * mp ); // I/O27

forall( dtype ostype | ostream( ostype ) ) ostype * ?|?( ostype * os, Int mp );28

The following factorial programs contrast using GMP with the C

A

and C interfaces, where the output29

from these programs appears in Figure 10. (Compile with flag lgmp to link with the GMP library.)30

C

A

C

#include <gmp>int main( void ) {

sout | "Factorial Numbers";Int fact = 1;

sout | 0 | fact;for ( unsigned int i = 1; i <= 40; i += 1 ) {

fact *= i;

sout | i | fact;}

}

#include <gmp.h>int main( void ) {

gmp printf( "Factorial Numbers\n" );mpz t fact;

mpz init set ui( fact, 1 );

gmp printf( "%d %Zd\n", 0, fact );for ( unsigned int i = 1; i <= 40; i += 1 ) {

mpz mul ui( fact, fact, i );

gmp printf( "%d %Zd\n", i, fact );}

}

31

J Rational Numbers32

Rational numbers are numbers written as a ratio, i.e., as a fraction, where the numerator (top number) and33

the denominator (bottom number) are whole numbers. When creating and computing with rational numbers,34

results are constantly reduced to keep the numerator and denominator as small as possible.35

// implementation36

struct Rational {37

Page 92: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

88 J Rational Numbers

Factorial Numbers0 1

1 1

2 23 6

4 245 120

6 720

7 50408 40320

9 362880

10 362880011 39916800

12 47900160013 6227020800

14 87178291200

15 130767436800016 20922789888000

17 35568742809600018 6402373705728000

19 121645100408832000

20 243290200817664000021 51090942171709440000

22 1124000727777607680000

23 2585201673888497664000024 620448401733239439360000

25 1551121004333098598400000026 403291461126605635584000000

27 10888869450418352160768000000

28 30488834461171386050150400000029 8841761993739701954543616000000

30 265252859812191058636308480000000

31 822283865417792281772556288000000032 263130836933693530167218012160000000

33 868331761881188649551819440128000000034 295232799039604140847618609643520000000

35 10333147966386144929666651337523200000000

36 37199332678990121746799944815083520000000037 13763753091226345046315979581580902400000000

38 52302261746660111176000722410007429120000000039 20397882081197443358640281739902897356800000000

40 815915283247897734345611269596115894272000000000

Figure 10: Multi-precision Factorials

Page 93: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

REFERENCES 89

long int numerator, denominator; // invariant: denominator > 01

}; // Rational2

3

Rational rational(); // constructors4

Rational rational( long int n );5

Rational rational( long int n, long int d );6

void ?{}( Rational * r, zero t );7

void ?{}( Rational * r, one t );8

9

long int numerator( Rational r ); // numerator/denominator getter/setter10

long int numerator( Rational r, long int n );11

long int denominator( Rational r );12

long int denominator( Rational r, long int d );13

14

int ?==?( Rational l, Rational r ); // comparison15

int ?!=?( Rational l, Rational r );16

int ?<?( Rational l, Rational r );17

int ?<=?( Rational l, Rational r );18

int ?>?( Rational l, Rational r );19

int ?>=?( Rational l, Rational r );20

21

Rational ?( Rational r ); // arithmetic22

Rational ?+?( Rational l, Rational r );23

Rational ? ?( Rational l, Rational r );24

Rational ?*?( Rational l, Rational r );25

Rational ?/?( Rational l, Rational r );26

27

double widen( Rational r ); // conversion28

Rational narrow( double f, long int md );29

30

forall( dtype istype | istream( istype ) ) istype * ?|?( istype *, Rational * ); // I/O31

forall( dtype ostype | ostream( ostype ) ) ostype * ?|?( ostype *, Rational );32

References33

[1] Ada12. Programming languages – Ada ISO/IEC 8652:2012. https://www.iso.org/standard/-34

61507.html, 3rd edition, 2012. 235

[2] Richard C. Bilson. Implementing overloading and polymorphism in C∀. Master’s thesis, School36

of Computer Science, University of Waterloo, Waterloo, Ontario, Canada, N2L 3G1, 2003. http://-37

plg.uwaterloo.ca/theses/BilsonThesis.pdf. 3, 4238

[3] Walter Bright and Andrei Alexandrescu. D Programming Language. Digital Mars, 2016. http://-39

dlang.org/spec/spec.html. 240

[4] P. A. Buhr. A case for teaching multi-exit loops to beginning programmers. SIGPLAN Not., 20(11):14–41

22, November 1985. 1342

[5] P. A. Buhr, David Till, and C. R. Zarnke. Assignment as the sole means of updating objects. Softw.43

Pract. Exper., 24(9):835–870, September 1994. 3, 3744

[6] C Programming Language ISO/IEC 9889:2011-12. https://www.iso.org/standard/57853.html, 3rd45

edition, 2012. 2, 20, 22, 41, 67, 7046

Page 94: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

90 REFERENCES

[7] C++ Programming Language ISO/IEC 14882:2014. https://www.iso.org/standard/64029.html, 4th1

edition, 2014. 2, 662

[8] Cobol14. Programming Languages – Cobol ISO/IEC 1989:2014. https://www.iso.org/standard/-3

51416.html, 2nd edition, 2014. 24

[9] G. V. Cormack and A. K. Wright. Polymorphism in the compiled language ForceOne. In Proceedings5

of the 20th Hawaii International Conference on Systems Sciences, pages 284–292, January 1987. 36

[10] G. V. Cormack and A. K. Wright. Type-dependent parameter inference. SIGPLAN Not., 25(6):127–7

136, June 1990. Proceedings of the ACM Sigplan’90 Conference on Programming Language Design8

and Implementation June 20-22, 1990, White Plains, New York, U.S.A. 3, 319

[11] Glen Jeffrey Ditchfield. Contextual Polymorphism. PhD thesis, Department of Computer Science,10

University of Waterloo, Waterloo, Ontario, Canada, N2L 3G1, 1992. http://plg.uwaterloo.ca/theses/-11

DitchfieldThesis.pdf. 312

[12] Tom Duff. Duff’s device. http://www.lysator.liu.se/c/duffs-device.html, November 1983. 1013

[13] Dominic Duggan, Gordon V. Cormack, and John Ophel. Kinded type inference for parametric over-14

loading. Acta Infomatica, 33(1):21–68, 1996. 315

[14] Margaret A. Ellis and Bjarne Stroustrup. The Annotated C++ Reference Manual. Addison-Wesley,16

Boston, 1st edition, 1990. 217

[15] Rodolfo Gabriel Esteves. C∀, a study in evolutionary design in programming languages. Master’s18

thesis, School of Computer Science, University of Waterloo, Waterloo, Ontario, Canada, N2L 3G1,19

2004. http://plg.uwaterloo.ca/theses/EstevesThesis.pdf. 320

[16] Fortran08. Programming Languages – Fortran Part 1:Base Language ISO/IEC 1539-1:2010. https://-21

www.iso.org/standard/50459.html, 3rd edition, 2010. 222

[17] Nissim Francez. Another advantage of keyword notation for parameter communication with subpro-23

grams. Communications of the ACM, 20(8):604–605, August 1977. 2924

[18] John Galletly. OCCAM 2: Including OCCAM 2.1. UCL (University College London) Press, London,25

2nd edition, 1996. 26, 4626

[19] GNU Multiple Precision Arithmetic Library. GNU, 2016. https://gmplib.org. 8427

[20] James Gosling, Bill Joy, Guy Steele, Gilad Bracha, and Alex Buckley. Java Language Specification,28

Java SE 8 edition, 2015. 229

[21] Robert Griesemer, Rob Pike, and Ken Thompson. Go Programming Language. Google, 2009. http://-30

golang.org/ref/spec. 231

[22] W. T. Hardgrave. Positional versus keyword parameter communication in programming languages.32

SIGPLAN Not., 11(5):52–58, May 1976. 2933

[23] Kathleen Jensen and Niklaus Wirth. Pascal User Manual and Report, ISO Pascal Standard. Springer–34

Verlag, 4th edition, 1991. Revised by Andrew B. Mickel and James F. Miner. 15, 1735

[24] C. H. Lindsey and S. G. van der Meulen. Informal Introduction to ALGOL 68. North-Holland, London,36

1977. 2137

[25] Barbara Liskov, Russell Atkinson, Toby Bloom, Eliot Moss, J. Craig Schaffert, Robert Scheifler, and38

Alan Snyder. CLU Reference Manual, volume 114 of Lecture Notes in Computer Science. Springer,39

New York, 1981. 26, 45, 4640

Page 95: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

REFERENCES 91

[26] Dennis M. Ritchie. The development of the C language. SIGPLAN Not., 28(3):201–208, March 1993.1

192

[27] Rust Programming Language, 2015. https://doc.rust-lang.org/reference.html. 23

[28] Bjarne Stroustrup. The C++ Programming Language. Addison-Wesley Series in Computer Science.4

Addison-Wesley, Boston, 1st edition, 1986. 15

[29] David W. Till. Tuples in imperative programming languages. Master’s thesis, Department of Computer6

Science, University of Waterloo, Waterloo, Ontario, Canada, N2L 3G1, 1989. 3, 36, 37, 38, 407

[30] TIOBE Index. http://www.tiobe.com/tiobe index. 28

[31] Ben Werther and Damian Conway. A modest proposal: C++ resyntaxed. SIGPLAN Not., 31(11):74–82,9

November 1996. 310

Page 96: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

Index

Italic page numbers give the location of the main1

entry for the referenced term. Plain page numbers2

denote uses of the indexed term. Entries for grammar3

non-terminals are italicized. A typewriter font is used4

for grammar terminals and program identifiers.5

!?, 596

*?, 597

++?, 598

+?, 599

?, 5910

help, 511

libcfa, 512

linemarks, 513

no linemarks, 514

no main, 515

no prelude, 516

prelude dir, 517

print, 518

prototypes, 519

statistics, 520

tree, 521

?, 5922

CFA, 423

L, 524

N, 525

P, 526

S, 527

debug, 428

fgnu89 inline, 429

h, 530

help, 431

l, 532

lgmp, 8733

m, 534

n, 535

nodebug, 436

nohelp, 437

noquiet, 438

p, 539

quiet, 440

std=gnu11, 441

t, 542

∼ , 1343

∼=, 1344

?!=?, 5945

?%=?, 5946

?%?, 5947

?&=?, 5948

?&?, 5949

?(), 5950

?*=?, 5951

?*?, 5952

?++, 5953

?+=?, 5954

?+?, 5955

? , 5956

? =?, 5957

? ?, 5958

?/=?, 5959

?/?, 5960

?<<=?, 5961

?<<?, 5962

?<=?, 5963

?<?, 5964

?==?, 5965

?=?, 5966

?>=?, 5967

?>>=?, 5968

?>>?, 5969

?>?, 5970

?[?], 5971

?\=?, 5972

?\?, 5973

\IeC {\textregistered }\\IeC {\textregistered }=?, 674

?\IeC {\textregistered }\\IeC {\textregistered }?, 675

?∧=?, 5976

?∧?, 5977

?|=?, 5978

?|?, 5979

CFA MAJOR , 480

CFA MINOR , 481

CFA PATCH , 482

CFA , 483

CFORALL , 484

cforall, 485

∼, 1386

∼=, 1387

∼?, 5988

92

Page 97: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

INDEX 93

abs, 731

acos, 772

acosh, 783

Ada, 2, 6, 324

address, 205

duality, 216

address duality, 237

addressing errors, 238

adelete, 729

aggregate, 1310

aggregation, 34, 3611

Algol68, 2112

aliasing, 3413

aligned alloc, 7014

alloc, 7115

alloc set, 7116

altexpr, 517

anew, 7218

arguments19

default, 2920

named, 2921

array, 2322

reference, 2323

ASCII, 4824

extended, 4825

ascodegen, 526

asin, 7727

asinh, 7828

assert.h, 7029

assignment, 2330

pointer, 2131

ast, 532

astdecl, 533

asterr, 534

astexpr, 535

astgen, 536

atan, 7737

atan2, 7738

atanh, 7839

ato, 7240

backward-compatible, 341

Bilson, Richard, 342

bin, 5043

bit field, 1944

box, 545

brand, 6146

break, 1347

break48

labelled, 1349

bsearch, 7350

bsearchl, 7351

bsearchu, 7352

C linkage, 353

C++, 1–3, 23, 32, 61, 62, 68, 7054

C-for-all, 155

C11, 256

calling convention, 357

calloc, 7058

cancellation59

pointer/reference, 2260

cbrt, 7661

ceil, 7962

cfa, 4, 563

C

A

, 164

clamp, 7465

closing coercion, 4466

cmemalign, 7167

Cobol, 268

codegen, 569

coercion, 2370

comma expression, 3371

compilation72

cfa, 473

compilation option74

CFA, 475

debug, 476

fgnu89 inline, 477

help, 478

nodebug, 479

nohelp, 480

noquiet, 481

quiet, 482

std=gnu11, 483

complex, 784

complex.h, 7085

const hell, 2586

constant87

underscore, 688

continue, 1389

continue90

labelled, 1391

copysign, 8092

coroutines, 6193

cos, 7794

Page 98: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

94 INDEX

cosh, 781

counters,heap,time,all,none, 52

ctordtor, 53

ctype.h, 704

D, 2, 61, 655

Dave Till, 36

declstats, 57

default arguments, 298

delete, 729

describe not prescribe, 110

Ditchfield, Glen, 311

div, 34, 7512

Doug Lea, 2613

duality, 2114

Duff’s device, 10, 1115

erf, 7816

erfc, 7817

errno.h, 7018

Esteves, Rodolfo, 319

excl( const char * scanset, char * s ), 5420

exp, 7521

exp2, 7522

expm1, 7523

exponentiation24

floating, 725

logarithm, 726

operator, 627

unsigned integral, 728

eye candy, 1329

fdim, 7530

fenv.h, 7031

Fibonacci, 6132

flattening coercion, 4533

float.h, 7034

floor, 7935

fma, 7536

fmod, 7437

Fortran, 238

frexp, 8039

fstream, 1, 440

fstream.hfa, 4741

garbage-collection, 142

regional, 143

gcc, 4, 5, 6044

Glen Ditchfield, 345

gmp, 84, 8746

gmp.h, 70, 8747

gnu, 448

Go, 2, 61, 62, 6549

goto, 1350

goto51

restricted, 1352

hex, 5153

hypot, 7654

I/O55

common case, 4756

separator, 4857

ignore( T & val ), 5358

ilogb, 7659

immutable, 2160

implicit output separation, 4861

implicit referencing, 2462

implicit separator, 4863

incl( const char * scanset, char * s ), 5364

initialization, 2365

input/output stream library, 4766

instruction decoding, 2167

Int, 8468

interoperability, 369

interposition, 570

inttypes.h, 7071

iostream, 172

iso646.h, 7073

Java, 2, 6, 23, 32, 6574

K-W C, 375

labelled76

break, 1377

continue, 1378

lambda, 3379

ldexp, 8080

Lea, Doug, 2681

left, 5282

level number, 483

lexical list, 4384

lgamma, 7885

library support, 386

limits.h, 7087

locale.h, 7088

log, 7589

Page 99: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

INDEX 95

log10, 761

log1p, 762

log2, 763

logarithm, 74

logb, 765

lrint, 796

lround, 797

lvalue, 22, 25, 45, 468

malloc, 709

malloc.h, 7010

mangling11

name, 3, 7012

manipulator, 48, 50, 5313

bin, 5014

excl, 5415

hex, 5116

ignore, 5317

incl, 5318

left, 5219

nl, 5020

nlOff, 5021

nlOn, 5022

nobase, 5123

nodp, 5124

oct, 5125

pad0, 5226

sci, 5127

sep, 4928

sepDisable, 4929

sepEnable, 4930

sepGet, 4931

sepGetTuple, 4932

sepOff, 4933

sepOn, 4934

sepSet, 4935

sepSetTuple, 4936

sepTuple, 4937

sign, 5138

skip, 5339

upcase, 5140

wd, 5141

wdi, 5342

ws, 5243

manipulators, 5044

mass, 3745

math.h, 7046

max, 7447

memalign, 7048

memcpy, 71, 7249

memory fault, 2150

memset, 71, 7251

Michael Tiemann, 2652

min, 7453

modf, 34, 8054

multi-level exit, 1355

multi-precision, 8456

multiple, 3757

multiple derivation, 1958

name hiding, 3259

name mangling, 360

named arguments, 2961

named return values, 2762

naming, 3463

nan, 7564

nearbyint, 7965

nested control-structure, 1366

new, 7267

newline separation, 5068

nextafter, 8069

nexttoward, 8070

nl, 5071

nlOff, 5072

nlOn, 5073

nobase, 5174

nodp, 5175

null-pointer constant, 2076

object, 2177

object-oriented, 1, 1778

oct, 5179

onion, 1980

opening coercion, 4581

operator82

exponentiation, 683

out parameter, 3484

overload, 385

pad0, 5286

parametric-polymorphic, 387

parse, 588

particle and wave, 2589

pointer, 19–2190

assignment, 2191

cancellation, 2292

pointer type, 2093

Page 100: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

96 INDEX

posix memalign, 701

pow, 752

pow(x,y), 63

power of a name, 34

prelude, 45

preprocessor variables6

CFA MINOR , 47

CFA PATCH , 48

CFA , 49

CFA , 410

CFORALL , 411

cforall, 412

prescribing, 2013

pretty, 514

productivity, 1, 1915

Python, 1, 47, 6516

qsort, 7317

random, 7418

Rational, 8719

realloc, 7020

reference, 2121

reference type, 20, 2222

referenced type, 2023

regional garbage-collection, 124

remainder, 7425

remquo, 7426

resolver, 527

return list, 2728

Richard Bilson, 329

rint, 7930

Rodolfo Esteves, 331

round, 7932

routine object, 2533

rproto, 534

rsteps, 535

Rust, 2, 61, 6536

rvalue, 22, 2537

safety, 1, 1938

scalbln, 8039

scalbn, 8040

sci, 5141

sentinel value, 2042

sep, 4943

sepDisable, 4944

sepEnable, 4945

sepGet, 4946

sepGetTuple, 4947

sepOff, 4948

sepOn, 4949

sepSet, 4950

sepSetTuple, 4951

sepTuple, 4952

setjmp.h, 7053

shell pipe-operator, 4754

sign, 5155

signal.h, 7056

sin, 7657

sinh, 7758

skip( const char * pattern ), 5359

sound, 2060

sout, 161

sqrt, 7662

srandom, 7463

static multi-level exit, 1364

stdalign.h, 7065

stdarg.h, 7066

stdatomic.h, 7067

stdbool.h, 7068

stddef.h, 7069

stdint.h, 7070

stdio.h, 1, 4, 7071

stdlib.h, 7072

stdnoreturn.h, 7073

sticky properties, 7074

stream library, 4775

string.h, 7076

structuring coercion, 4577

swap, 7478

symevt, 579

tan, 7780

tanh, 7881

tentative definitions, 6882

tgamma, 7983

tgmath.h, 7084

threads.h, 7085

Tiemann, Michael, 2686

Till, Dave, 387

time.h, 7088

translator option89

help, 590

libcfa, 591

linemarks, 592

no linemarks, 593

Page 101: TCTC A 1 (Cforall) User Manual 2 Version 1.0 3 “describe not prescribe” C A Team Andrew Beach, Richard Bilson, Peter A. Buhr, Thierry Delisle, Glen Ditchfield, Rodolfo G. Esteves,

INDEX 97

no main, 51

no prelude, 52

print, 53

print4

altexpr, 55

ascodegen, 56

astdecl, 57

asterr, 58

astgen, 59

ast, 510

box, 511

codegen, 512

ctordtor, 513

declstats, 514

parse, 515

pretty, 516

resolver, 517

rproto, 518

rsteps, 519

symevt, 520

tree, 521

tuple, 522

prototypes, 523

statistics24

counters,heap,time,all,none, 525

tree, 526

L, 527

N, 528

P, 529

altexpr, 530

ascodegen, 531

astdecl, 532

asterr, 533

astexpr, 534

astgen, 535

ast, 536

box, 537

codegen, 538

ctordtor, 539

declstats, 540

parse, 541

pretty, 542

resolver, 543

rproto, 544

rsteps, 545

symevt, 546

tree, 547

tuple, 548

S49

counters,heap,time,all,none, 550

h, 551

l, 552

m, 553

n, 554

p, 555

t, 556

tree, 557

trunc, 7958

tuple, 33, 4759

tuple, 560

tuple assignment, 3761

tuple expression, 3562

tuple type, 35, 4363

tuple variable, 3564

tuple-returning functions, 3565

type hoisting, 3266

type nesting, 3267

uchar.h, 7068

undefined, 21, 2869

underscore, 670

unistd.h, 7071

unsound, 2172

upcase, 5173

version number, 474

warning, 2675

wchar.h, 7076

wctype.h, 7077

wd, 5178

wdi, 5379

What goes around, comes around., 380

ws( unsigned char minimum, unsigned char significant, floating point81

5282