Changes in / [6250a312:0f9bef3]


Ignore:
Files:
4 added
23 deleted
44 edited

Legend:

Unmodified
Added
Removed
  • Jenkins/FullBuild

    r6250a312 r0f9bef3  
    99
    1010        try {
    11                 //Wrap build to add timestamp to command line
    12                 wrap([$class: 'TimestamperBuildWrapper']) {
     11                //Prevent the build from exceeding 30 minutes
     12                timeout(60) {
    1313
    14                         stage('Build') {
     14                        //Wrap build to add timestamp to command line
     15                        wrap([$class: 'TimestamperBuildWrapper']) {
    1516
    16                                 results = [null, null]
     17                                stage 'Build'
    1718
    18                                 parallel (
    19                                         gcc_6_x64: { trigger_build( 'gcc-6',   'x64', true  ) },
    20                                         gcc_6_x86: { trigger_build( 'gcc-6',   'x86', true  ) },
    21                                         gcc_5_x64: { trigger_build( 'gcc-5',   'x64', false ) },
    22                                         gcc_5_x86: { trigger_build( 'gcc-5',   'x86', false ) },
    23                                         gcc_4_x64: { trigger_build( 'gcc-4.9', 'x64', false ) },
    24                                         gcc_4_x86: { trigger_build( 'gcc-4.9', 'x86', false ) },
    25                                         clang_x64: { trigger_build( 'clang',   'x64', false ) },
    26                                         clang_x86: { trigger_build( 'clang',   'x86', false ) },
    27                                 )
     19                                        results = [null, null]
     20
     21                                        parallel (
     22                                                gcc_6_x64: { trigger_build( 'gcc-6',   'x64', true  ) },
     23                                                gcc_6_x86: { trigger_build( 'gcc-6',   'x86', true  ) },
     24                                                gcc_5_x64: { trigger_build( 'gcc-5',   'x64', false ) },
     25                                                gcc_5_x86: { trigger_build( 'gcc-5',   'x86', false ) },
     26                                                gcc_4_x64: { trigger_build( 'gcc-4.9', 'x64', false ) },
     27                                                gcc_4_x86: { trigger_build( 'gcc-4.9', 'x86', false ) },
     28                                                clang_x64: { trigger_build( 'clang',   'x64', false ) },
     29                                                clang_x86: { trigger_build( 'clang',   'x86', false ) },
     30                                        )
     31
     32                                //Push latest changes to do-lang repo
     33                                push_build()
    2834                        }
    29 
    30                         //Push latest changes to do-lang repo
    31                         push_build()
    3235                }
    3336        }
     
    9699def push_build() {
    97100        //Don't use the build_stage function which outputs the compiler
    98         stage('Push') {
     101        stage 'Push'
    99102
    100103                status_prefix = 'Push'
     
    119122                //sh "GIT_SSH_COMMAND=\"ssh -v\" git push DoLang ${gitRefNewValue}:master"
    120123                echo('BUILD NOT PUSH SINCE DO-LANG SERVER WAS DOWN')
    121         }
    122124}
    123125
  • Jenkinsfile

    r6250a312 r0f9bef3  
    2828                wrap([$class: 'TimestamperBuildWrapper']) {
    2929
    30                         notify_server()
    31 
    32                         prepare_build()
    33 
    34                         checkout()
    35 
    36                         build()
    37 
    38                         test()
    39 
    40                         benchmark()
    41 
    42                         clean()
    43 
    44                         build_doc()
    45 
    46                         publish()
    47 
    48                         notify_server()
     30                        //Prevent the build from exceeding 60 minutes
     31                        timeout(60) {
     32
     33                                notify_server()
     34
     35                                prepare_build()
     36
     37                                checkout()
     38
     39                                build()
     40
     41                                test()
     42
     43                                benchmark()
     44
     45                                clean()
     46
     47                                build_doc()
     48
     49                                publish()
     50
     51                                notify_server()
     52                        }
    4953                }
    5054        }
     
    8589def collect_git_info() {
    8690
    87         checkout scm
    88 
    8991        //create the temporary output directory in case it doesn't already exist
    9092        def out_dir = pwd tmp: true
     
    9395        //parse git logs to find what changed
    9496        gitRefName = env.BRANCH_NAME
    95         sh "git reflog > ${out_dir}/GIT_COMMIT"
     97        dir("../${gitRefName}@script") {
     98                sh "git reflog > ${out_dir}/GIT_COMMIT"
     99        }
    96100        git_reflog = readFile("${out_dir}/GIT_COMMIT")
    97101        gitRefOldValue = (git_reflog =~ /moving from (.+) to (.+)/)[0][1]
     
    166170}
    167171
    168 def build_stage(String name, Closure block ) {
     172def build_stage(String name) {
    169173        stage_name = name
    170         stage(name, block)
     174        stage name
    171175}
    172176
     
    241245//Compilation script is done here but environnement set-up and error handling is done in main loop
    242246def checkout() {
    243         build_stage('Checkout') {
     247        build_stage'Checkout'
    244248                //checkout the source code and clean the repo
    245249                checkout scm
     
    250254                //Reset the git repo so no local changes persist
    251255                sh 'git reset --hard'
    252         }
    253256}
    254257
    255258def build() {
    256         build_stage('Build') {
     259        build_stage'Build'
    257260       
    258261                def install_dir = pwd tmp: true
     
    266269                //Compile the project
    267270                sh 'make -j 8 --no-print-directory V=0 install'
    268         }
    269271}
    270272
    271273def test() {
    272         build_stage('Test') {
     274        build_stage'Test'
    273275
    274276                //Run the tests from the tests directory
    275277                if ( do_alltests ) {
    276                         sh 'make -C src/tests all-tests debug=yes --no-print-directory'
    277                         sh 'make -C src/tests all-tests debug=no --no-print-directory'
     278                        sh 'make -C src/tests all-tests debug=yes'
     279                        sh 'make -C src/tests all-tests debug=no'
    278280                }
    279281                else {
    280                         sh 'make -C src/tests --no-print-directory'
    281                 }
    282         }
     282                        sh 'make -C src/tests'
     283                }
    283284}
    284285
    285286def benchmark() {
    286         build_stage('Benchmark') {
     287        build_stage'Benchmark'
    287288
    288289                if( !do_benchmark ) return
     
    293294                //Append bench results
    294295                sh 'make -C src/benchmark --no-print-directory csv-data >> bench.csv'
    295         }
    296296}
    297297
    298298def clean() {
    299         build_stage('Cleanup') {
     299        build_stage'Cleanup'
    300300
    301301                //do a maintainer-clean to make sure we need to remake from scratch
    302302                sh 'make maintainer-clean > /dev/null'
    303         }
    304303}
    305304
    306305def build_doc() {
    307         build_stage('Documentation') {
     306        build_stage'Documentation'
    308307
    309308                if( !do_doc ) return
     
    316315                        make_doc()
    317316                }
    318         }
    319317}
    320318
    321319def publish() {
    322         build_stage('Publish') {
     320        build_stage'Publish'
    323321
    324322                if( !do_publish ) return
     
    326324                //Then publish the results
    327325                sh 'curl --silent --data @bench.csv http://plg2:8082/jenkins/publish > /dev/null || true'
    328         }
    329326}
    330327
     
    374371"""
    375372
    376         def email_to = "pabuhr@uwaterloo.ca, rschlunt@uwaterloo.ca, a3moss@uwaterloo.ca, tdelisle@uwaterloo.ca, brice.dobry@huawei.com, ajbeach@edu.uwaterloo.ca"
     373        def email_to = "pabuhr@uwaterloo.ca, rschlunt@uwaterloo.ca, a3moss@uwaterloo.ca, tdelisle@uwaterloo.ca, brice.dobry@huawei.com"
    377374
    378375        //send email notification
  • doc/rob_thesis/cfa-format.tex

    r6250a312 r0f9bef3  
    1 % \usepackage{xcolor}
    2 % \usepackage{listings}
     1\usepackage{xcolor}
     2\usepackage{listings}
    33% \usepackage{booktabs}
    44% \usepackage{array}
     
    103103
    104104\renewcommand{\ttdefault}{pcr}
    105 
    106 \newcommand{\basicstylesmall}{\scriptsize\ttfamily\color{basicCol}}
    107105
    108106\lstdefinestyle{defaultStyle}{
     
    133131  style=defaultStyle
    134132}
    135 \lstMakeShortInline[basewidth=0.5em,breaklines=true,breakatwhitespace,basicstyle=\normalsize\ttfamily\color{basicCol}]@  % single-character for \lstinline
     133\lstMakeShortInline[basewidth=0.5em,breaklines=true,basicstyle=\normalsize\ttfamily\color{basicCol}]@  % single-character for \lstinline
    136134
    137135\lstnewenvironment{cfacode}[1][]{
     
    197195\newcommand{\one}{\lstinline{one_t}\xspace}
    198196\newcommand{\ateq}{\lstinline{\@=}\xspace}
    199 
    200 \newenvironment{newtext}{\color{red}}{\ignorespacesafterend}
    201197
    202198% \lstset{ %
  • doc/rob_thesis/conclusions.tex

    r6250a312 r0f9bef3  
    66On the surface, the work may appear as a rehash of similar mechanisms in \CC.
    77However, every added feature is different than its \CC counterpart, often with extended functionality, better integration with C and its programmers, and always supports separate compilation.
    8 All of these new features are being used extensively by the \CFA development-team to build the \CFA runtime system.
    9 In particular, the concurrency system is built on top of RAII, library functions @new@ and @delete@ are used to manage dynamically allocated objects, and tuples are used to provide uniform interfaces to C library routines such as @div@ and @remquo@.
     8All of these new features are being used by the \CFA development-team to build the \CFA runtime system.
    109
    1110\section{Constructors and Destructors}
     
    246245That is, structure fields can be accessed and modified by any block of code without restriction, so while it is possible to ensure that an object is initially set to a valid state, it is not possible to ensure that it remains in a consistent state throughout its lifetime.
    247246A popular technique for ensuring consistency in object-oriented programming languages is to provide access modifiers such as @private@, which provides compile-time checks that only privileged code accesses private data.
    248 This approach could be added to \CFA, but it requires an idiomatic way of specifying what code is privileged and what data is protected.
     247This approach could be added to \CFA, but it requires an idiomatic way of specifying what code is privileged.
    249248One possibility is to tie access control into an eventual module system.
    250 
    251 \begin{sloppypar}
    252 The current implementation of implicit subobject-construction is currently an all-or-nothing check.
    253 That is, if a subobject is conditionally constructed, \eg within an if-statement, no implicit constructors for that object are added.
    254 \begin{cfacode}
    255 struct A { ... };
    256 void ?{}(A * a) { ... }
    257 
    258 struct B {
    259   A a;
    260 };
    261 void ?{}(B * b) {
    262   if (...) {
    263     (&b->a){};  // explicitly constructed
    264   } // does not construct in else case
    265 }
    266 \end{cfacode}
    267 This behaviour is unsafe and breaks the guarantee that constructors fully initialize objects.
    268 This situation should be properly handled, either by examining all paths and inserting implicit constructor calls only in the paths missing construction, or by emitting an error or warning.
    269 \end{sloppypar}
    270249
    271250\subsection{Tuples}
     
    273252This feature ties nicely into named tuples, as seen in D and Swift.
    274253
    275 Currently, tuple flattening and structuring conversions are 0-cost conversions in the resolution algorithm.
     254Currently, tuple flattening and structuring conversions are 0-cost.
    276255This makes tuples conceptually very simple to work with, but easily causes unnecessary ambiguity in situations where the type system should be able to differentiate between alternatives.
    277256Adding an appropriate cost function to tuple conversions will allow tuples to interact with the rest of the programming language more cohesively.
  • doc/rob_thesis/ctordtor.tex

    r6250a312 r0f9bef3  
    66% doesn't seem possible to do this without allowing ttype on generic structs?
    77
    8 Since \CFA is a true systems language, it does not require a garbage collector.
    9 As well, \CFA is not an object-oriented programming language, \ie, structures cannot have methods.
    10 While structures can have function pointer members, this is different from methods, since methods have implicit access to structure members and methods cannot be reassigned.
     8Since \CFA is a true systems language, it does not provide a garbage collector.
     9As well, \CFA is not an object-oriented programming language, \ie, structures cannot have routine members.
    1110Nevertheless, one important goal is to reduce programming complexity and increase safety.
    1211To that end, \CFA provides support for implicit pre/post-execution of routines for objects, via constructors and destructors.
     
    3332The key difference between assignment and initialization being that assignment occurs on a live object (\ie, an object that contains data).
    3433It is important to note that this means @x@ could have been used uninitialized prior to being assigned, while @y@ could not be used uninitialized.
    35 Use of uninitialized variables yields undefined behaviour \cite[p.~558]{C11}, which is a common source of errors in C programs.
     34Use of uninitialized variables yields undefined behaviour, which is a common source of errors in C programs.
    3635
    3736Initialization of a declaration is strictly optional, permitting uninitialized variables to exist.
     
    7170int x2 = opaque_get(x, 2);
    7271\end{cfacode}
    73 This pattern is cumbersome to use since every access becomes a function call, requiring awkward syntax and a performance cost.
     72This pattern is cumbersome to use since every access becomes a function call.
    7473While useful in some situations, this compromise is too restrictive.
    7574Furthermore, even with this idiom it is easy to make mistakes, such as forgetting to destroy an object or destroying it multiple times.
    7675
    7776A constructor provides a way of ensuring that the necessary aspects of object initialization is performed, from setting up invariants to providing compile- and run-time checks for appropriate initialization parameters.
    78 This goal is achieved through a \emph{guarantee} that a constructor is called \emph{implicitly} after every object is allocated from a type with associated constructors, as part of an object's \emph{definition}.
    79 Since a constructor is called on every object of a managed type, it is \emph{impossible} to forget to initialize such objects, as long as all constructors perform some sensible form of initialization.
     77This goal is achieved through a guarantee that a constructor is called implicitly after every object is allocated from a type with associated constructors, as part of an object's definition.
     78Since a constructor is called on every object of a managed type, it is impossible to forget to initialize such objects, as long as all constructors perform some sensible form of initialization.
    8079
    8180In \CFA, a constructor is a function with the name @?{}@.
     
    115114In other words, a default constructor is a constructor that takes a single argument: the @this@ parameter.
    116115
    117 In \CFA, a destructor is a function much like a constructor, except that its name is \lstinline!^?{}! \footnote{Originally, the name @~?{}@ was chosen for destructors, to provide familiarity to \CC programmers. Unforunately, this name causes parsing conflicts with the bitwise-not operator when used with operator syntax (see section \ref{sub:syntax}.)} and it takes only one argument.
     116In \CFA, a destructor is a function much like a constructor, except that its name is \lstinline!^?{}! and it takes only one argument.
    118117A destructor for the @Array@ type can be defined as:
    119118\begin{cfacode}
     
    136135On line 2, @z@ is initialized with the value of @x@, while on line 3, @y@ is assigned the value of @x@.
    137136The key distinction between initialization and assignment is that a value to be initialized does not hold any meaningful values, whereas an object to be assigned might.
    138 In particular, these cases cannot be handled the same way because in the former case @z@ has no array, while @y@ does.
    139 A \emph{copy constructor} is used to perform initialization using another object of the same type.
     137In particular, these cases cannot be handled the same way because in the former case @z@ does not currently own an array, while @y@ does.
    140138
    141139\begin{cfacode}[emph={other}, emphstyle=\color{red}]
     
    153151}
    154152\end{cfacode}
    155 The two functions above handle the cases of initialization and assignment.
    156 The first function is called a copy constructor, because it constructs its argument by copying the values from another object of the same type.
     153The two functions above handle these cases.
     154The first function is called a \emph{copy constructor}, because it constructs its argument by copying the values from another object of the same type.
    157155The second function is the standard copy-assignment operator.
    158 \CFA does not currently have the concept of reference types, so the most appropriate type for the source object in copy constructors and assignment operators is a value type.
    159 Appropriate care is taken in the implementation to avoid recursive calls to the copy constructor.
    160156The four functions (default constructor, destructor, copy constructor, and assignment operator) are special in that they safely control the state of most objects.
    161157
     
    220216A * y = malloc();  // copy construct: ?{}(&y, malloc())
    221217
     218?{}(&x);    // explicit construct x, second construction
     219?{}(y, x);  // explit construct y from x, second construction
    222220^?{}(&x);   // explicit destroy x, in different order
    223 ?{}(&x);    // explicit construct x, second construction
    224221^?{}(y);    // explicit destroy y
    225 ?{}(y, x);  // explit construct y from x, second construction
    226222
    227223// implicit ^?{}(&y);
     
    283279\end{cfacode}
    284280In this example, @malloc@ dynamically allocates storage and initializes it using a constructor, all before assigning it into the variable @x@.
    285 Intuitively, the expression-resolver determines that @malloc@ returns some type @T *@, as does the constructor expression since it returns the type of its argument.
    286 This type flows outwards to the declaration site where the expected type is known to be @X *@, thus the first argument to the constructor must be @X *@, narrowing the search space.
    287 
    288281If this extension is not present, constructing dynamically allocated objects is much more cumbersome, requiring separate initialization of the pointer and initialization of the pointed-to memory.
    289282\begin{cfacode}
     
    307300It should be noted that this technique is not exclusive to @malloc@, and allows a user to write a custom allocator that can be idiomatically used in much the same way as a constructed @malloc@ call.
    308301
    309 While it is possible to use operator syntax with destructors, destructors invalidate their argument, thus operator syntax with destructors is void-typed expression.
     302It should be noted that while it is possible to use operator syntax with destructors, destructors invalidate their argument, thus operator syntax with destructors is a statement and does not produce a value.
    310303
    311304\subsection{Function Generation}
     
    315308If the translator can expect these functions to exist, then it can unconditionally attempt to resolve them.
    316309Moreover, the existence of a standard interface allows polymorphic code to interoperate with new types seamlessly.
    317 While automatic generation of assignment functions is present in previous versions of \CFA, the the implementation has been largely rewritten to accomodate constructors and destructors.
    318310
    319311To mimic the behaviour of standard C, the default constructor and destructor for all of the basic types and for all pointer types are defined to do nothing, while the copy constructor and assignment operator perform a bitwise copy of the source parameter (as in \CC).
    320 This default is intended to maintain backwards compatibility and performance, by not imposing unexpected operations for a C programmer, as a zero-default behaviour would.
    321 However, it is possible for a user to define such constructors so that variables are safely zeroed by default, if desired.
    322 %%%%%%%%%%%%%%%%%%%%%%%%%% line width %%%%%%%%%%%%%%%%%%%%%%%%%%
    323 \begin{cfacode}
    324 void ?{}(int * i) { *i = 0; }
    325 forall(dtype T) void ?{}(T ** p) { *p = 0; }  // any pointer type
    326 void f() {
    327   int x;    // initialized to 0
    328   int * p;  // initialized to 0
    329 }
    330 \end{cfacode}
    331 %%%%%%%%%%%%%%%%%%%%%%%%%% line width %%%%%%%%%%%%%%%%%%%%%%%%%%
    332312
    333313There are several options for user-defined types: structures, unions, and enumerations.
    334314To aid in ease of use, the standard set of four functions is automatically generated for a user-defined type after its definition is completed.
    335315By auto-generating these functions, it is ensured that legacy C code continues to work correctly in every context where \CFA expects these functions to exist, since they are generated for every complete type.
    336 As well, these functions are always generated, since they may be needed by polymorphic functions.
    337 With that said, the generated functions are not called implicitly unless they are non-trivial, and are never exported, making it simple for the optimizer to strip them away when they are not used.
    338316
    339317The generated functions for enumerations are the simplest.
     
    360338}
    361339\end{cfacode}
    362 In the future, \CFA will introduce strongly-typed enumerations, like those in \CC, wherein enumerations create a new type distinct from @int@ so that integral values require an explicit cast to be stored in an enumeration variable.
     340In the future, \CFA will introduce strongly-typed enumerations, like those in \CC.
    363341The existing generated routines are sufficient to express this restriction, since they are currently set up to take in values of that enumeration type.
    364342Changes related to this feature only need to affect the expression resolution phase, where more strict rules will be applied to prevent implicit conversions from integral types to enumeration types, but should continue to permit conversions from enumeration types to @int@.
     
    514492In addition to freedom, \ateq provides a simple path for migrating legacy C code to \CFA, in that objects can be moved from C-style initialization to \CFA gradually and individually.
    515493It is worth noting that the use of unmanaged objects can be tricky to get right, since there is no guarantee that the proper invariants are established on an unmanaged object.
    516 It is recommended that most objects be managed by sensible constructors and destructors, except where absolutely necessary, such as memory-mapped devices, trigger devices, I/O controllers, etc.
     494It is recommended that most objects be managed by sensible constructors and destructors, except where absolutely necessary.
    517495
    518496When a user declares any constructor or destructor, the corresponding intrinsic/generated function and all field constructors for that type are hidden, so that they are not found during expression resolution until the user-defined function goes out of scope.
     
    567545\end{cfacode}
    568546However, if the translator sees a sub-object used within the body of a constructor, but does not see a constructor call that uses the sub-object as the target of a constructor, then the translator assumes the object is to be implicitly constructed (copy constructed in a copy constructor and default constructed in any other constructor).
    569 To override this rule, \ateq can be used to force the translator to trust the programmer's discretion.
    570 This form of \ateq is not yet implemented.
    571547\begin{cfacode}
    572548void ?{}(A * a) {
     
    580556}
    581557
    582 void ?{}(A * a, int x) {
    583   // object forwarded to another constructor,
    584   // does not implicitly construct any members
    585   (&a){};
    586 }
    587 
    588558void ^?{}(A * a) {
    589559  ^(&a->x){}; // explicit destructor call
    590560} // z, y, w implicitly destructed, in this order
    591561\end{cfacode}
    592 If at any point, the @this@ parameter is passed directly as the target of another constructor, then it is assumed the other constructor handles the initialization of all of the object's members and no implicit constructor calls are added to the current constructor.
     562If at any point, the @this@ parameter is passed directly as the target of another constructor, then it is assumed that constructor handles the initialization of all of the object's members and no implicit constructor calls are added.
     563To override this rule, \ateq can be used to force the translator to trust the programmer's discretion.
     564This form of \ateq is not yet implemented.
    593565
    594566Despite great effort, some forms of C syntax do not work well with constructors in \CFA.
     
    647619The body of @A@ has been omitted, since only the constructor interfaces are important.
    648620
    649 It should be noted that unmanaged objects, i.e. objects that have only trivial constructors, can still make use of designations and nested initializers in \CFA.
     621It should be noted that unmanaged objects can still make use of designations and nested initializers in \CFA.
    650622It is simple to overcome this limitation for managed objects by making use of compound literals, so that the arguments to the constructor call are explicitly typed.
    651 %%%%%%%%%%%%%%%%%%%%%%%%%% line width %%%%%%%%%%%%%%%%%%%%%%%%%%
    652 \begin{cfacode}
    653 struct B { int x; };
    654 struct C { int y; };
    655 struct A { B b; C c; };
    656 void ?{}(A *, B);
    657 void ?{}(A *, C);
    658 
    659 A a = {
    660   (C){ 10 } // disambiguate with compound literal
    661 };
    662 \end{cfacode}
    663 %%%%%%%%%%%%%%%%%%%%%%%%%% line width %%%%%%%%%%%%%%%%%%%%%%%%%%
    664623
    665624\subsection{Implicit Destructors}
     
    785744\end{cfacode}
    786745
    787 While \CFA supports the GCC computed-goto extension, the behaviour of managed objects in combination with computed-goto is undefined.
    788 \begin{cfacode}
    789 void f(int val) {
    790   void * l = val == 0 ? &&L1 : &&L2;
    791   {
    792       A x;
    793     L1: ;
    794       goto *l;  // branches differently depending on argument
    795   }
    796   L2: ;
    797 }
    798 \end{cfacode}
    799 Likewise, destructors are not executed at scope-exit due to a computed-goto in \CC, as of g++ version 6.2.
    800 
    801746\subsection{Implicit Copy Construction}
    802747\label{s:implicit_copy_construction}
     
    805750Exempt from these rules are intrinsic and built-in functions.
    806751It should be noted that unmanaged objects are subject to copy constructor calls when passed as arguments to a function or when returned from a function, since they are not the \emph{target} of the copy constructor call.
    807 That is, since the parameter is not marked as an unmanaged object using \ateq, it is copy constructed if it is returned by value or passed as an argument to another function, so to guarantee consistent behaviour, unmanaged objects must be copy constructed when passed as arguments.
     752That is, since the parameter is not marked as an unmanaged object using \ateq, it is be copy constructed if it is returned by value or passed as an argument to another function, so to guarantee consistent behaviour, unmanaged objects must be copy constructed when passed as arguments.
    808753These semantics are important to bear in mind when using unmanaged objects, and could produce unexpected results when mixed with objects that are explicitly constructed.
    809754\begin{cfacode}
    810 struct A { ... };
     755struct A;
    811756void ?{}(A *);
    812757void ?{}(A *, A);
     
    865810It should be noted that reference types will allow specifying that a value does not need to be copied, however reference types do not provide a means of preventing implicit copy construction from uses of the reference, so the problem is still present when passing or returning the reference by value.
    866811
    867 Adding implicit copy construction imposes the additional runtime cost of the copy constructor for every argument and return value in a function call.
    868 This cost is necessary to maintain appropriate value semantics when calling a function.
    869 In the future, return-value-optimization (RVO) can be implemented for \CFA to elide unnecessary copy construction and destruction of temporary objects.
    870 This cost is not present for types with trivial copy constructors and destructors.
    871 
    872812A known issue with this implementation is that the argument and return value temporaries are not guaranteed to have the same address for their entire lifetimes.
    873813In the previous example, since @_retval_f@ is allocated and constructed in @f@, then returned by value, the internal data is bitwise copied into the caller's stack frame.
     
    968908\subsection{Array Initialization}
    969909Arrays are a special case in the C type-system.
    970 Type checking largely ignores size information for C arrays, making it impossible to write a standalone \CFA function that constructs or destructs an array, while maintaining the standard interface for constructors and destructors.
     910C arrays do not carry around their size, making it impossible to write a standalone \CFA function that constructs or destructs an array while maintaining the standard interface for constructors and destructors.
    971911Instead, \CFA defines the initialization and destruction of an array recursively.
    972912That is, when an array is defined, each of its elements is constructed in order from element 0 up to element $n-1$.
     
    12071147\end{cfacode}
    12081148
    1209 This implementation comes at the runtime cost of an additional branch for every @static@ local variable, each time the function is called.
    1210 Since initializers are not required to be compile-time constant expressions, they can involve global variables, function arguments, function calls, etc.
    1211 As a direct consequence, @static@ local variables cannot be initialized with an attribute-constructor routines like global variables can.
    1212 However, in the case where the variable is unmanaged and has a compile-time constant initializer, a C-compliant initializer is generated and the additional cost is not present.
    1213 \CC shares the same semantics for its @static@ local variables.
    1214 
    12151149\subsection{Polymorphism}
    12161150As mentioned in section \ref{sub:polymorphism}, \CFA currently has 3 type-classes that are used to designate polymorphic data types: @otype@, @dtype@, and @ftype@.
     
    12381172These additions allow @f@'s body to create and destroy objects of type @T@, and pass objects of type @T@ as arguments to other functions, following the normal \CFA rules.
    12391173A point of note here is that objects can be missing default constructors (and eventually other functions through deleted functions), so it is important for \CFA programmers to think carefully about the operations needed by their function, as to not over-constrain the acceptable parameter types and prevent potential reuse.
    1240 
    1241 These additional assertion parameters impose a runtime cost on all managed temporary objects created in polymorphic code, even those with trivial constructors and destructors.
    1242 This cost is necessary because polymorphic code does not know the actual type at compile-time, due to separate compilation.
    1243 Since trivial constructors and destructors either do not perform operations or are simply bit-wise copy operations, the imposed cost is essentially the cost of the function calls.
    1244 
    1245 \section{Summary}
    1246 
    1247 When creating a new object of a managed type, it is guaranteed that a constructor is be called to initialize the object at its definition point, and is destructed when the object's lifetime ends.
    1248 Destructors are called in the reverse order of construction.
    1249 
    1250 Every argument passed to a function is copy constructed into a temporary object that is passed by value to the functions and destructed at the end of the statement.
    1251 Function return values are copy constructed inside the function at the return statement, passed by value to the call-site, and destructed at the call-site at the end of the statement.
    1252 
    1253 Every complete object type has a default constructor, copy constructor, assignment operator, and destructor.
    1254 To accomplish this, these functions are generated as appropriate for new types.
    1255 User-defined functions shadow built-in and automatically generated functions, so it is possible to specialize the behaviour of a type.
    1256 Furthermore, default constructors and aggregate field constructors are hidden when \emph{any} constructor is defined.
    1257 
    1258 Objects dynamically allocated with @malloc@, \ateq objects, and objects with only trivial constructors and destructors are unmanaged.
    1259 Unmanaged objects are never the target of an implicit constructor or destructor call.
  • doc/rob_thesis/intro.tex

    r6250a312 r0f9bef3  
    1919Unfortunately, \CC is actively diverging from C, so incremental additions require significant effort and training, coupled with multiple legacy design-choices that cannot be updated.
    2020
    21 The current implementation of \CFA is a source-to-source translator from \CFA to GNU C \cite{GCCExtensions}.
    22 
    23 The remainder of this section describes some of the important features that currently exist in \CFA, to give the reader the necessary context in which the new features presented in this thesis must dovetail.
     21The remainder of this section describes some of the important new features that currently exist in \CFA, to give the reader the necessary context in which the new features presented in this thesis must dovetail.
    2422
    2523\subsection{C Background}
    2624\label{sub:c_background}
    27 In the context of this work, the term \emph{object} refers to a region of data storage in the execution environment, the contents of which can represent values \cite[p.~6]{C11}.
    28 
    2925One of the lesser-known features of standard C is \emph{designations}.
    3026Designations are similar to named parameters in languages such as Python and Scala, except that they only apply to aggregate initializers.
    31 Note that in \CFA, designations use a colon separator, rather than an equals sign as in C, because this syntax is one of the few places that conflicts with the new language features.
    3227\begin{cfacode}
    3328struct A {
     
    4843Later initializers override earlier initializers, so a sub-object for which there is more than one initializer is only initialized by its last initializer.
    4944These semantics can be seen in the initialization of @a0@, where @x@ is designated twice, and thus initialized to @8@.
     45Note that in \CFA, designations use a colon separator, rather than an equals sign as in C, because this syntax is one of the few places that conflicts with the new language features.
    5046
    5147C also provides \emph{compound literal} expressions, which provide a first-class mechanism for creating unnamed objects.
     
    6157Compound literals create an unnamed object, and result in an lvalue, so it is legal to assign a value into a compound literal or to take its address \cite[p.~86]{C11}.
    6258Syntactically, compound literals look like a cast operator followed by a brace-enclosed initializer, but semantically are different from a C cast, which only applies basic conversions and coercions and is never an lvalue.
    63 
    64 The \CFA translator makes use of several GNU C extensions, including \emph{nested functions} and \emph{attributes}.
    65 Nested functions make it possible to access data that is lexically in scope in the nested function's body.
    66 \begin{cfacode}
    67 int f() {
    68   int x = 0;
    69   void g() {
    70     x++;
    71   }
    72   g();  // changes x
    73 }
    74 \end{cfacode}
    75 Nested functions come with the usual C caveat that they should not leak into the containing environment, since they are only valid as long as the containing function's stack frame is active.
    76 
    77 Attributes make it possible to inform the compiler of certain properties of the code.
    78 For example, a function can be marked as deprecated, so that legacy APIs can be identified and slowly removed, or as \emph{hot}, so that the compiler knows the function is called frequently and should be aggresively optimized.
    79 \begin{cfacode}
    80 __attribute__((deprecated("foo is deprecated, use bar instead")))
    81 void foo();
    82 __attribute__((hot)) void bar(); // heavily optimized
    83 
    84 foo();  // warning
    85 bar();
    86 \end{cfacode}
    8759
    8860\subsection{Overloading}
     
    9264C provides a small amount of built-in overloading, \eg + is overloaded for the basic types.
    9365Like in \CC, \CFA allows user-defined overloading based both on the number of parameters and on the types of parameters.
    94 \begin{cfacode}
    95 void f(void);  // (1)
    96 void f(int);   // (2)
    97 void f(char);  // (3)
    98 
    99 f('A');        // selects (3)
    100 \end{cfacode}
     66  \begin{cfacode}
     67  void f(void);  // (1)
     68  void f(int);   // (2)
     69  void f(char);  // (3)
     70
     71  f('A');        // selects (3)
     72  \end{cfacode}
    10173In this case, there are three @f@ procedures, where @f@ takes either 0 or 1 arguments, and if an argument is provided then it may be of type @int@ or of type @char@.
    10274Exactly which procedure is executed depends on the number and types of arguments passed.
    10375If there is no exact match available, \CFA attempts to find a suitable match by examining the C built-in conversion heuristics.
    104 The \CFA expression resolution algorithm uses a cost function to determine the interpretation that uses the fewest conversions and polymorphic type bindings.
    105 \begin{cfacode}
    106 void g(long long);
    107 
    108 g(12345);
    109 \end{cfacode}
     76  \begin{cfacode}
     77  void g(long long);
     78
     79  g(12345);
     80  \end{cfacode}
    11081In the above example, there is only one instance of @g@, which expects a single parameter of type @long long@.
    11182Here, the argument provided has type @int@, but since all possible values of type @int@ can be represented by a value of type @long long@, there is a safe conversion from @int@ to @long long@, and so \CFA calls the provided @g@ routine.
    11283
    113 Overloading solves the problem present in C where there can only be one function with a given name, requiring multiple names for functions that perform the same operation but take in different types.
    114 This can be seen in the example of the absolute value functions C:
    115 \begin{cfacode}
    116 // stdlib.h
    117 int abs(int);
    118 long int labs(long int);
    119 long long int llabs(long long int);
    120 \end{cfacode}
    121 In \CFA, the functions @labs@ and @llabs@ are replaced by appropriate overloads of @abs@.
    122 
    12384In addition to this form of overloading, \CFA also allows overloading based on the number and types of \emph{return} values.
    12485This extension is a feature that is not available in \CC, but is available in other programming languages such as Ada \cite{Ada95}.
    125 \begin{cfacode}
    126 int g();         // (1)
    127 double g();      // (2)
    128 
    129 int x = g();     // selects (1)
    130 \end{cfacode}
     86  \begin{cfacode}
     87  int g();         // (1)
     88  double g();      // (2)
     89
     90  int x = g();     // selects (1)
     91  \end{cfacode}
    13192Here, the only difference between the signatures of the different versions of @g@ is in the return values.
    13293The result context is used to select an appropriate routine definition.
    13394In this case, the result of @g@ is assigned into a variable of type @int@, so \CFA prefers the routine that returns a single @int@, because it is an exact match.
    134 
    135 Return-type overloading solves similar problems to parameter-list overloading, in that multiple functions that perform similar operations can have the same, but produce different values.
    136 One use case for this feature is to provide two versions of the @bsearch@ routine:
    137 \begin{cfacode}
    138 forall(otype T | { int ?<?( T, T ); })
    139 T * bsearch(T key, const T * arr, size_t dimension) {
    140   int comp(const void * t1, const void * t2) {
    141     return *(T *)t1 < *(T *)t2 ? -1 : *(T *)t2 < *(T *)t1 ? 1 : 0;
    142   }
    143   return (T *)bsearch(&key, arr, dimension, sizeof(T), comp);
    144 }
    145 forall(otype T | { int ?<?( T, T ); })
    146 unsigned int bsearch(T key, const T * arr, size_t dimension) {
    147   T *result = bsearch(key, arr, dimension);
    148   // pointer subtraction includes sizeof(T)
    149   return result ? result - arr : dimension;
    150 }
    151 double key = 5.0;
    152 double vals[10] = { /* 10 floating-point values */ };
    153 
    154 double * val = bsearch( 5.0, vals, 10 ); // selection based on return type
    155 int posn = bsearch( 5.0, vals, 10 );
    156 \end{cfacode}
    157 The first version provides a thin wrapper around the C @bsearch@ routine, converting untyped @void *@ to the polymorphic type @T *@, allowing the \CFA compiler to catch errors when the type of @key@, @arr@, and the target at the call-site do not agree.
    158 The second version provides an alternate return of the index in the array of the selected element, rather than its address.
    15995
    16096There are times when a function should logically return multiple values.
     
    209145
    210146An extra quirk introduced by multiple return values is in the resolution of function calls.
    211 \begin{cfacode}
    212 int f();            // (1)
    213 [int, int] f();     // (2)
    214 
    215 void g(int, int);
    216 
    217 int x, y;
    218 [x, y] = f();       // selects (2)
    219 g(f());             // selects (2)
    220 \end{cfacode}
     147  \begin{cfacode}
     148  int f();            // (1)
     149  [int, int] f();     // (2)
     150
     151  void g(int, int);
     152
     153  int x, y;
     154  [x, y] = f();       // selects (2)
     155  g(f());             // selects (2)
     156  \end{cfacode}
    221157In this example, the only possible call to @f@ that can produce the two @int@s required for assigning into the variables @x@ and @y@ is the second option.
    222158A similar reasoning holds calling the function @g@.
    223 
    224 This duality between aggregation and aliasing can be seen in the C standard library in the @div@ and @remquo@ functions, which return the quotient and remainder for a division of integer and floating-point values, respectively.
    225 \begin{cfacode}
    226 typedef struct { int quo, rem; } div_t; // from stdlib.h
    227 div_t div( int num, int den );
    228 double remquo( double num, double den, int * quo );
    229 div_t qr = div( 13, 5 );            // return quotient/remainder aggregate
    230 int q;
    231 double r = remquo( 13.5, 5.2, &q ); // return remainder, alias quotient
    232 \end{cfacode}
    233 @div@ aggregates the quotient/remainder in a structure, while @remquo@ aliases a parameter to an argument.
    234 Alternatively, a programming language can directly support returning multiple values, \eg in \CFA:
    235 \begin{lstlisting}
    236 [int, int] div(int num, int den);               // return two integers
    237 [double, double] div( double num, double den ); // return two doubles
    238 int q, r;                     // overloaded variable names
    239 double q, r;
    240 [q, r] = div(13, 5);          // select appropriate div and q, r
    241 [q, r] = div(13.5, 5.2);
    242 \end{lstlisting}
    243159
    244160In \CFA, overloading also applies to operator names, known as \emph{operator overloading}.
    245161Similar to function overloading, a single operator is given multiple meanings by defining new versions of the operator with different signatures.
    246162In \CC, this can be done as follows
    247 \begin{cppcode}
    248 struct A { int i; };
    249 A operator+(A x, A y);
    250 bool operator<(A x, A y);
    251 \end{cppcode}
     163  \begin{cppcode}
     164  struct A { int i; };
     165  int operator+(A x, A y);
     166  bool operator<(A x, A y);
     167  \end{cppcode}
    252168
    253169In \CFA, the same example can be written as follows.
    254 \begin{cfacode}
    255 struct A { int i; };
    256 A ?+?(A x, A y);    // '?'s represent operands
    257 int ?<?(A x, A y);
    258 \end{cfacode}
     170  \begin{cfacode}
     171  struct A { int i; };
     172  int ?+?(A x, A y);    // '?'s represent operands
     173  bool ?<?(A x, A y);
     174  \end{cfacode}
    259175Notably, the only difference is syntax.
    260176Most of the operators supported by \CC for operator overloading are also supported in \CFA.
     
    263179Finally, \CFA also permits overloading variable identifiers.
    264180This feature is not available in \CC.
    265 \begin{cfacode}
    266 struct Rational { int numer, denom; };
    267 int x = 3;               // (1)
    268 double x = 1.27;         // (2)
    269 Rational x = { 4, 11 };  // (3)
    270 
    271 void g(double);
    272 
    273 x += 1;                  // chooses (1)
    274 g(x);                    // chooses (2)
    275 Rational y = x;          // chooses (3)
    276 \end{cfacode}
     181  \begin{cfacode}
     182  struct Rational { int numer, denom; };
     183  int x = 3;               // (1)
     184  double x = 1.27;         // (2)
     185  Rational x = { 4, 11 };  // (3)
     186
     187  void g(double);
     188
     189  x += 1;                  // chooses (1)
     190  g(x);                    // chooses (2)
     191  Rational y = x;          // chooses (3)
     192  \end{cfacode}
    277193In this example, there are three definitions of the variable @x@.
    278194Based on the context, \CFA attempts to choose the variable whose type best matches the expression context.
     
    292208Due to these rewrite rules, the values @0@ and @1@ have the types \zero and \one in \CFA, which allow for overloading various operations that connect to @0@ and @1@ \footnote{In the original design of \CFA, @0@ and @1@ were overloadable names \cite[p.~7]{cforall}.}.
    293209The types \zero and \one have special built-in implicit conversions to the various integral types, and a conversion to pointer types for @0@, which allows standard C code involving @0@ and @1@ to work as normal.
    294 \begin{cfacode}
    295 // lvalue is similar to returning a reference in C++
    296 lvalue Rational ?+=?(Rational *a, Rational b);
    297 Rational ?=?(Rational * dst, zero_t) {
    298   return *dst = (Rational){ 0, 1 };
    299 }
    300 
    301 Rational sum(Rational *arr, int n) {
    302   Rational r;
    303   r = 0;     // use rational-zero_t assignment
    304   for (; n > 0; n--) {
    305     r += arr[n-1];
    306   }
    307   return r;
    308 }
    309 \end{cfacode}
     210  \begin{cfacode}
     211  // lvalue is similar to returning a reference in C++
     212  lvalue Rational ?+=?(Rational *a, Rational b);
     213  Rational ?=?(Rational * dst, zero_t) {
     214    return *dst = (Rational){ 0, 1 };
     215  }
     216
     217  Rational sum(Rational *arr, int n) {
     218    Rational r;
     219    r = 0;     // use rational-zero_t assignment
     220    for (; n > 0; n--) {
     221      r += arr[n-1];
     222    }
     223    return r;
     224  }
     225  \end{cfacode}
    310226This function takes an array of @Rational@ objects and produces the @Rational@ representing the sum of the array.
    311227Note the use of an overloaded assignment operator to set an object of type @Rational@ to an appropriate @0@ value.
     
    316232In particular, \CFA supports the notion of parametric polymorphism.
    317233Parametric polymorphism allows a function to be written generically, for all values of all types, without regard to the specifics of a particular type.
    318 For example, in \CC, the simple identity function for all types can be written as:
    319 \begin{cppcode}
    320 template<typename T>
    321 T identity(T x) { return x; }
    322 \end{cppcode}
    323 \CC uses the template mechanism to support parametric polymorphism. In \CFA, an equivalent function can be written as:
    324 \begin{cfacode}
    325 forall(otype T)
    326 T identity(T x) { return x; }
    327 \end{cfacode}
     234For example, in \CC, the simple identity function for all types can be written as
     235  \begin{cppcode}
     236  template<typename T>
     237  T identity(T x) { return x; }
     238  \end{cppcode}
     239\CC uses the template mechanism to support parametric polymorphism. In \CFA, an equivalent function can be written as
     240  \begin{cfacode}
     241  forall(otype T)
     242  T identity(T x) { return x; }
     243  \end{cfacode}
    328244Once again, the only visible difference in this example is syntactic.
    329245Fundamental differences can be seen by examining more interesting examples.
    330 In \CC, a generic sum function is written as follows:
    331 \begin{cppcode}
    332 template<typename T>
    333 T sum(T *arr, int n) {
    334   T t;  // default construct => 0
    335   for (; n > 0; n--) t += arr[n-1];
    336   return t;
    337 }
    338 \end{cppcode}
     246In \CC, a generic sum function is written as follows
     247  \begin{cppcode}
     248  template<typename T>
     249  T sum(T *arr, int n) {
     250    T t;  // default construct => 0
     251    for (; n > 0; n--) t += arr[n-1];
     252    return t;
     253  }
     254  \end{cppcode}
    339255Here, the code assumes the existence of a default constructor, assignment operator, and an addition operator over the provided type @T@.
    340256If any of these required operators are not available, the \CC compiler produces an error message stating which operators could not be found.
    341257
    342 A similar sum function can be written in \CFA as follows:
    343 \begin{cfacode}
    344 forall(otype T | **R**{ T ?=?(T *, zero_t); T ?+=?(T *, T); }**R**)
    345 T sum(T *arr, int n) {
    346   T t = 0;
    347   for (; n > 0; n--) t = t += arr[n-1];
    348   return t;
    349 }
    350 \end{cfacode}
     258A similar sum function can be written in \CFA as follows
     259  \begin{cfacode}
     260  forall(otype T | **R**{ T ?=?(T *, zero_t); T ?+=?(T *, T); }**R**)
     261  T sum(T *arr, int n) {
     262    T t = 0;
     263    for (; n > 0; n--) t = t += arr[n-1];
     264    return t;
     265  }
     266  \end{cfacode}
    351267The first thing to note here is that immediately following the declaration of @otype T@ is a list of \emph{type assertions} that specify restrictions on acceptable choices of @T@.
    352268In particular, the assertions above specify that there must be an assignment from \zero to @T@ and an addition assignment operator from @T@ to @T@.
    353269The existence of an assignment operator from @T@ to @T@ and the ability to create an object of type @T@ are assumed implicitly by declaring @T@ with the @otype@ type-class.
    354270In addition to @otype@, there are currently two other type-classes.
    355 
    356 @dtype@, short for \emph{data type}, serves as the top type for object types; any object type, complete or incomplete, can be bound to a @dtype@ type variable.
    357 To contrast, @otype@, short for \emph{object type}, is a @dtype@ with known size, alignment, and an assignment operator, and thus bind only to complete object types.
    358 With this extra information, complete objects can be used in polymorphic code in the same way they are used in monomorphic code, providing familiarity and ease of use.
    359 The third type-class is @ftype@, short for \emph{function type}, matching only function types.
    360271The three type parameter kinds are summarized in \autoref{table:types}
    361272
     
    364275    \begin{tabular}{|c||c|c|c||c|c|c|}
    365276                                                                                                    \hline
    366     name    & object type & incomplete type & function type & can assign & can create & has size \\ \hline
     277    name    & object type & incomplete type & function type & can assign value & can create & has size \\ \hline
    367278    @otype@ & X           &                 &               & X                & X          & X        \\ \hline
    368279    @dtype@ & X           & X               &               &                  &            &          \\ \hline
     
    377288In contrast, the explicit nature of assertions allows \CFA's polymorphic functions to be separately compiled, as the function prototype states all necessary requirements separate from the implementation.
    378289For example, the prototype for the previous sum function is
    379 \begin{cfacode}
    380 forall(otype T | **R**{ T ?=?(T *, zero_t); T ?+=?(T *, T); }**R**)
    381 T sum(T *arr, int n);
    382 \end{cfacode}
     290  \begin{cfacode}
     291  forall(otype T | **R**{ T ?=?(T *, zero_t); T ?+=?(T *, T); }**R**)
     292  T sum(T *arr, int n);
     293  \end{cfacode}
    383294With this prototype, a caller in another translation unit knows all of the constraints on @T@, and thus knows all of the operations that need to be made available to @sum@.
    384295
    385296In \CFA, a set of assertions can be factored into a \emph{trait}.
    386297\begin{cfacode}
    387 trait Addable(otype T) {
    388   T ?+?(T, T);
    389   T ++?(T);
    390   T ?++(T);
    391 }
    392 forall(otype T | Addable(T)) void f(T);
    393 forall(otype T | Addable(T) | { T --?(T); }) T g(T);
    394 forall(otype T, U | Addable(T) | { T ?/?(T, U); }) U h(T, U);
     298  trait Addable(otype T) {
     299    T ?+?(T, T);
     300    T ++?(T);
     301    T ?++(T);
     302  }
     303  forall(otype T | Addable(T)) void f(T);
     304  forall(otype T | Addable(T) | { T --?(T); }) T g(T);
     305  forall(otype T, U | Addable(T) | { T ?/?(T, U); }) U h(T, U);
    395306\end{cfacode}
    396307This capability allows specifying the same set of assertions in multiple locations, without the repetition and likelihood of mistakes that come with manually writing them out for each function declaration.
    397308
    398 An interesting application of return-type resolution and polymorphism is a polymorphic version of @malloc@.
     309An interesting application of return-type resolution and polymorphism is a type-safe version of @malloc@.
    399310\begin{cfacode}
    400311forall(dtype T | sized(T))
     
    410321The built-in trait @sized@ ensures that size and alignment information for @T@ is available in the body of @malloc@ through @sizeof@ and @_Alignof@ expressions respectively.
    411322In calls to @malloc@, the type @T@ is bound based on call-site information, allowing \CFA code to allocate memory without the potential for errors introduced by manually specifying the size of the allocated block.
    412 
    413 \subsection{Planned Features}
    414 
    415 One of the planned features \CFA is \emph{reference types}.
    416 At a high level, the current proposal is to add references as a way to cleanup pointer syntax.
    417 With references, it will be possible to store any address, as with a pointer, with the key difference being that references are automatically dereferenced.
    418 \begin{cfacode}
    419 int x = 0;
    420 int * p = &x;  // needs &
    421 int & ref = x; // no &
    422 
    423 printf("%d %d\n", *p, ref); // pointer needs *, ref does not
    424 \end{cfacode}
    425 
    426 It is possible to add new functions or shadow existing functions for the duration of a scope, using normal C scoping rules.
    427 One application of this feature is to reverse the order of @qsort@.
    428 \begin{cfacode}
    429 forall(otype T | { int ?<?( T, T ); })
    430 void qsort(const T * arr, size_t size) {
    431   int comp(const void * t1, const void * t2) {
    432     return *(T *)t1 < *(T *)t2 ? -1 : *(T *)t2 < *(T *)t1 ? 1 : 0;
    433   }
    434   qsort(arr, dimension, sizeof(T), comp);
    435 
    436 }
    437 double vals[10] = { ... };
    438 qsort(vals, 10);                // ascending order
    439 {
    440   int ?<?(double x, double y) { // locally override behaviour
    441     return x > y;
    442   }
    443   qsort(vals, 10);              // descending sort
    444 }
    445 \end{cfacode}
    446 Currently, there is no way to \emph{remove} a function from consideration from the duration of a scope.
    447 For example, it may be desirable to eliminate assignment from a scope, to reduce accidental mutation.
    448 To address this desire, \emph{deleted functions} are a planned feature for \CFA.
    449 \begin{cfacode}
    450 forall(otype T) void f(T *);
    451 
    452 int x = 0;
    453 f(&x);  // might modify x
    454 {
    455   int ?=?(int *, int) = delete;
    456   f(&x);   // error, no assignment for int
    457 }
    458 \end{cfacode}
    459 Now, if the deleted function is chosen as the best match, the expression resolver emits an error.
    460323
    461324\section{Invariants}
     
    587450\end{javacode}
    588451In Java 7, a new \emph{try-with-resources} construct was added to alleviate most of the pain of working with resources, but ultimately it still places the burden squarely on the user rather than on the library designer.
    589 Furthermore, for complete safety this pattern requires nested objects to be declared separately, otherwise resources that can throw an exception on close can leak nested resources \footnote{Since close is only guaranteed to be called on objects declared in the try-list and not objects passed as constructor parameters, the @B@ object may not be closed in @new A(new B())@ if @A@'s close raises an exception.} \cite{TryWithResources}.
     452Furthermore, for complete safety this pattern requires nested objects to be declared separately, otherwise resources that can throw an exception on close can leak nested resources \cite{TryWithResources}.
    590453\begin{javacode}
    591454public void write(String filename, String msg) throws Exception {
     
    658521% these are declared in the struct, so they're closer to C++ than to CFA, at least syntactically. Also do not allow for default constructors
    659522% D has a GC, which already makes the situation quite different from C/C++
    660 The programming language D also manages resources with constructors and destructors \cite{D}.
    661 In D, @struct@s are stack allocatable and managed via scoping like in \CC, whereas @class@es are managed automatically by the garbage collector.
     523The programming language, D, also manages resources with constructors and destructors \cite{D}.
     524In D, @struct@s are stack allocated and managed via scoping like in \CC, whereas @class@es are managed automatically by the garbage collector.
    662525Like Java, using the garbage collector means that destructors are called indeterminately, requiring the use of finally statements to ensure dynamically allocated resources that are not managed by the garbage collector, such as open files, are cleaned up.
    663526Since D supports RAII, it is possible to use the same techniques as in \CC to ensure that resources are released in a timely manner.
     
    892755
    893756Type-safe variadic functions are added to \CFA and discussed in Chapter 4.
    894 
    895 \section{Contributions}
    896 \label{s:contributions}
    897 
    898 No prior work on constructors or destructors had been done for \CFA.
    899 I did both the design and implementation work.
    900 While the overall design is based on constructors and destructors in object-oriented C++, it had to be re-engineered into non-object-oriented \CFA.
    901 I also had to make changes to the \CFA expression-resolver to integrate constructors and destructors into the type system.
    902 
    903 Prior work on the design of tuples for \CFA was done by Till, and some initial implementation work by Esteves.
    904 I largely took the Till design but added tuple indexing, which exists in a number of programming languages with tuples, simplified the implicit tuple conversions, and integrated with the \CFA polymorphism and assertion satisfaction model.
    905 I did a new implementation of tuples, and extensively
    906 augmented initial work by Bilson to incorporate tuples into the \CFA expression-resolver and type-unifier.
    907 
    908 No prior work on variadic functions had been done for \CFA.
    909 I did both the design and implementation work.
    910 While the overall design is based on variadic templates in C++, my design is novel in the way it is incorporated into the \CFA polymorphism model, and is engineered into \CFA so it dovetails with tuples.
  • doc/rob_thesis/thesis-frontpgs.tex

    r6250a312 r0f9bef3  
    8686%\newpage
    8787
    88 % A C K N O W L E D G E M E N T S
    89 % -------------------------------
     88% % A C K N O W L E D G E M E N T S
     89% % -------------------------------
    9090
    91 \begin{center}\textbf{Acknowledgements}\end{center}
     91% \begin{center}\textbf{Acknowledgements}\end{center}
    9292
    93 I would like to thank my supervisor, Professor Peter Buhr, for all of his help, including reading the many drafts of this thesis and providing guidance throughout my degree.
    94 This work would not have been as enjoyable, nor would it have been as strong without Peter's knowledge, help, and encouragement.
    95 
    96 I would like to thank my readers, Professors Gregor Richards and Patrick Lam for all of their helpful feedback.
    97 
    98 Thanks to Aaron Moss and Thierry Delisle for many helpful discussions, both work-related and not, and for all of the work they have put into the \CFA project.
    99 This thesis would not have been the same without their efforts.
    100 
    101 I thank Glen Ditchfield and Richard Bilson, for all of their help with both the design and implementation of \CFA.
    102 
    103 I thank my partner, Erin Blackmere, for all of her love and support.
    104 Without her, I would not be who I am today.
    105 
    106 Thanks to my parents, Bob and Jackie Schluntz, for their love and support throughout my life, and for always encouraging me to be my best.
    107 
    108 Thanks to my best friends, Travis Bartlett, Abraham Dubrisingh, and Kevin Wu, whose companionship is always appreciated.
    109 The time we've spent together over the past 4 years has always kept me entertained.
    110 An extra shout-out to Kaleb Alway, Max Bardakov, Ten Bradley, and Ed Lee, with whom I've shared many a great meal; thank you for being my friend.
    111 
    112 Finally, I would like to acknowledge financial support in the form of a David R. Cheriton Graduate Scholarship and a corporate partnership with Huawei Ltd.
    113 
    114 \cleardoublepage
    115 %\newpage
     93% % I would like to thank all the little people who made this possible.
     94% TODO
     95% \cleardoublepage
     96% %\newpage
    11697
    11798% % D E D I C A T I O N
  • doc/rob_thesis/thesis.tex

    r6250a312 r0f9bef3  
    118118\usepackage[pdftex]{graphicx} % For including graphics N.B. pdftex graphics driver
    119119
    120 \usepackage{xcolor}
    121 \usepackage{listings}
    122 
    123120\input{cfa-format.tex}
    124121
     
    141138    pdftitle={Resource Management and Tuples in \CFA},    % title: CHANGE THIS TEXT!
    142139    pdfauthor={Rob Schluntz},    % author: CHANGE THIS TEXT! and uncomment this line
    143     pdfsubject={Programming Languages},  % subject: CHANGE THIS TEXT! and uncomment this line
     140%    pdfsubject={Subject},  % subject: CHANGE THIS TEXT! and uncomment this line
    144141%    pdfkeywords={keyword1} {key2} {key3}, % list of keywords, and uncomment this line if desired
    145142    pdfnewwindow=true,      % links in new window
  • doc/rob_thesis/tuples.tex

    r6250a312 r0f9bef3  
    161161\end{cfacode}
    162162
    163 \begin{sloppypar}
    164163In addition to variables of tuple type, it is also possible to have pointers to tuples, and arrays of tuples.
    165 Tuple types can be composed of any types, except for array types, since array assignment is disallowed, which makes tuple assignment difficult when a tuple contains an array.
     164Tuple types can be composed of any types, except for array types, since arrays do not carry their size around, which makes tuple assignment difficult when a tuple contains an array.
    166165\begin{cfacode}
    167166[double, int] di;
     
    170169\end{cfacode}
    171170This examples declares a variable of type @[double, int]@, a variable of type pointer to @[double, int]@, and an array of ten @[double, int]@.
    172 \end{sloppypar}
    173171
    174172\subsection{Tuple Indexing}
     
    214212The flexible structure of tuples permits a simple and expressive function-call syntax to work seamlessly with both single- and multiple-return-value functions, and with any number of arguments of arbitrarily complex structure.
    215213
    216 In \KWC \cite{Buhr94a,Till89}, there were 4 tuple coercions: opening, closing, flattening, and structuring.
     214In \KWC \cite{Buhr94a,Till89}, a precursor to \CFA, there were 4 tuple coercions: opening, closing, flattening, and structuring.
    217215Opening coerces a tuple value into a tuple of values, while closing converts a tuple of values into a single tuple value.
    218216Flattening coerces a nested tuple into a flat tuple, \ie it takes a tuple with tuple components and expands it into a tuple with only non-tuple components.
     
    220218
    221219In \CFA, the design has been simplified to require only the two conversions previously described, which trigger only in function call and return situations.
    222 This simplification is a primary contribution of this thesis to the design of tuples in \CFA.
    223220Specifically, the expression resolution algorithm examines all of the possible alternatives for an expression to determine the best match.
    224221In resolving a function call expression, each combination of function value and list of argument alternatives is examined.
     
    257254Let $L_i$ for $i$ in $[0, n)$ represent each component of the flattened left side, $R_i$ represent each component of the flattened right side of a multiple assignment, and $R$ represent the right side of a mass assignment.
    258255
    259 For a multiple assignment to be valid, both tuples must have the same number of elements when flattened.
    260 For example, the following is invalid because the number of components on the left does not match the number of components on the right.
    261 \begin{cfacode}
    262 [int, int] x, y, z;
    263 [x, y] = z;   // multiple assignment, invalid 4 != 2
    264 \end{cfacode}
    265 Multiple assignment assigns $R_i$ to $L_i$ for each $i$.
     256For a multiple assignment to be valid, both tuples must have the same number of elements when flattened. Multiple assignment assigns $R_i$ to $L_i$ for each $i$.
    266257That is, @?=?(&$L_i$, $R_i$)@ must be a well-typed expression.
    267258In the previous example, @[x, y] = z@, @z@ is flattened into @z.0, z.1@, and the assignments @x = z.0@ and @y = z.1@ happen.
     
    274265
    275266Both kinds of tuple assignment have parallel semantics, such that each value on the left side and right side is evaluated \emph{before} any assignments occur.
    276 As a result, it is possible to swap the values in two variables without explicitly creating any temporary variables or calling a function.
     267As a result, it is possible to swap the values in two variables without explicitly creating any temporary variables or calling a function,
    277268\begin{cfacode}
    278269int x = 10, y = 20;
     
    305296\subsection{Tuple Construction}
    306297Tuple construction and destruction follow the same rules and semantics as tuple assignment, except that in the case where there is no right side, the default constructor or destructor is called on each component of the tuple.
    307 As constructors and destructors did not exist in previous versions of \CFA or in \KWC, this is a primary contribution of this thesis to the design of tuples.
    308298\begin{cfacode}
    309299struct S;
     
    443433\section{Casting}
    444434In C, the cast operator is used to explicitly convert between types.
    445 In \CFA, the cast operator has a secondary use, which is type ascription, since it forces the expression resolution algorithm to choose the lowest cost conversion to the target type.
     435In \CFA, the cast operator has a secondary use, which is type ascription, since it force the expression resolution algorithm to choose the lowest cost conversion to the target type.
    446436That is, a cast can be used to select the type of an expression when it is ambiguous, as in the call to an overloaded function.
    447437\begin{cfacode}
     
    497487\section{Polymorphism}
    498488Due to the implicit flattening and structuring conversions involved in argument passing, @otype@ and @dtype@ parameters are restricted to matching only with non-tuple types.
    499 The integration of polymorphism, type assertions, and monomorphic specialization of tuple-assertions are a primary contribution of this thesis to the design of tuples.
    500489\begin{cfacode}
    501490forall(otype T, dtype U)
     
    535524It is also important to note that these calls could be disambiguated if the function return types were different, as they likely would be for a reasonable implementation of @?+?@, since the return type is used in overload resolution.
    536525Still, these semantics are a deficiency of the current argument matching algorithm, and depending on the function, differing return values may not always be appropriate.
    537 These issues could be rectified by applying an appropriate conversion cost to the structuring and flattening conversions, which are currently 0-cost conversions in the expression resolver.
     526These issues could be rectified by applying an appropriate cost to the structuring and flattening conversions, which are currently 0-cost conversions.
    538527Care would be needed in this case to ensure that exact matches do not incur such a cost.
    539528\begin{cfacode}
     
    570559\section{Implementation}
    571560Tuples are implemented in the \CFA translator via a transformation into generic types.
    572 Generic types are an independent contribution developed at the same time.
    573 The transformation into generic types and the generation of tuple-specific code are primary contributions of this thesis to tuples.
    574 
    575561The first time an $N$-tuple is seen for each $N$ in a scope, a generic type with $N$ type parameters is generated.
    576562For example,
  • doc/rob_thesis/variadic.tex

    r6250a312 r0f9bef3  
    55\section{Design Criteria} % TODO: better section name???
    66C provides variadic functions through the manipulation of @va_list@ objects.
    7 In C, a variadic function is one which contains at least one parameter, followed by @...@ as the last token in the parameter list.
    8 In particular, some form of \emph{argument descriptor} or \emph{sentinel value} is needed to inform the function of the number of arguments and their types.
     7A variadic function is one which contains at least one parameter, followed by @...@ as the last token in the parameter list.
     8In particular, some form of \emph{argument descriptor} is needed to inform the function of the number of arguments and their types.
    99Two common argument descriptors are format strings or counter parameters.
    10 It is important to note that both of these mechanisms are inherently redundant, because they require the user to explicitly specify information that the compiler already knows \footnote{While format specifiers can convey some information the compiler does not know, such as whether to print a number in decimal or hexadecimal, the number of arguments is wholly redundant.}.
     10It is important to note that both of these mechanisms are inherently redundant, because they require the user to explicitly specify information that the compiler already knows.
    1111This required repetition is error prone, because it is easy for the user to add or remove arguments without updating the argument descriptor.
    1212In addition, C requires the programmer to hard code all of the possible expected types.
     
    152152That is to say, the programmer who writes @sum@ does not need full program knowledge of every possible data type, unlike what is necessary to write an equivalent function using the standard C mechanisms.
    153153
    154 \begin{sloppypar}
    155154Going one last step, it is possible to achieve full generality in \CFA, allowing the summation of arbitrary lists of summable types.
    156155\begin{cfacode}
     
    171170\end{cfacode}
    172171The \CFA translator requires adding explicit @double ?+?(int, double)@ and @double ?+?(double, int)@ functions for this call to work, since implicit conversions are not supported for assertions.
    173 \end{sloppypar}
    174172
    175173A notable limitation of this approach is that it heavily relies on recursive assertions.
     
    228226In the call to @new@, @Array@ is selected to match @T@, and @Params@ is expanded to match @[int, int, int, int]@. To satisfy the assertions, a constructor with an interface compatible with @void ?{}(Array *, int, int, int)@ must exist in the current scope.
    229227
    230 The @new@ function provides the combination of polymorphic @malloc@ with a constructor call, so that it becomes impossible to forget to construct dynamically-allocated objects.
     228The @new@ function provides the combination of type-safe @malloc@ with a constructor call, so that it becomes impossible to forget to construct dynamically-allocated objects.
    231229This approach provides the type-safety of @new@ in \CC, without the need to specify the allocated type, thanks to return-type inference.
    232230
  • src/CodeGen/CodeGenerator.cc

    r6250a312 r0f9bef3  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tus May  9 16:50:00 2017
    13 // Update Count     : 484
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Mar 30 16:38:01 2017
     13// Update Count     : 482
    1414//
    1515
     
    4141namespace CodeGen {
    4242        int CodeGenerator::tabsize = 4;
    43 
    44         // Pseudo Function: output << lineDirective(currentNode);
    45     struct lineDirective {
    46         CodeLocation const & loc;
    47                 lineDirective(CodeLocation const & location) : loc(location) {}
    48                 lineDirective(BaseSyntaxNode const * node) : loc(node->location) {}
    49         };
    50         std::ostream & operator<<(std::ostream & out, lineDirective const & ld) {
    51                 if (ld.loc.isSet())
    52                         return out << "\n# " << ld.loc.linenumber << " \""
    53                                 << ld.loc.filename << "\"\n";
    54                 return out << "\n// Unset Location\n";
    55         }
    5643
    5744        // the kinds of statements that would ideally be followed by whitespace
     
    141128
    142129
    143         // *** Declarations
     130        //*** Declarations
    144131        void CodeGenerator::visit( FunctionDecl * functionDecl ) {
    145                 output << lineDirective( functionDecl );
    146 
    147132                extension( functionDecl );
    148133                genAttributes( functionDecl->get_attributes() );
     
    168153                }
    169154
    170                 output << lineDirective( objectDecl );
    171 
    172155                extension( objectDecl );
    173156                genAttributes( objectDecl->get_attributes() );
     
    209192                        cur_indent += CodeGenerator::tabsize;
    210193                        for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end(); i++ ) {
    211                                 output << lineDirective( *i ) << indent;
     194                                output << indent;
    212195                                (*i)->accept( *this );
    213196                                output << ";" << endl;
     
    221204
    222205        void CodeGenerator::visit( StructDecl * structDecl ) {
    223                 output << lineDirective( structDecl );
    224 
    225206                extension( structDecl );
    226207                handleAggregate( structDecl, "struct " );
     
    228209
    229210        void CodeGenerator::visit( UnionDecl * unionDecl ) {
    230                 output << lineDirective( unionDecl );
    231 
    232211                extension( unionDecl );
    233212                handleAggregate( unionDecl, "union " );
     
    236215        void CodeGenerator::visit( EnumDecl * enumDecl ) {
    237216                extension( enumDecl );
    238                 output << lineDirective ( enumDecl );
    239217                output << "enum ";
    240218                genAttributes( enumDecl->get_attributes() );
     
    252230                                ObjectDecl * obj = dynamic_cast< ObjectDecl* >( *i );
    253231                                assert( obj );
    254                                 output << lineDirective( obj ) << indent << mangleName( obj );
     232                                output << indent << mangleName( obj );
    255233                                if ( obj->get_init() ) {
    256234                                        output << " = ";
     
    270248        void CodeGenerator::visit( TypedefDecl * typeDecl ) {
    271249                assertf( ! genC, "Typedefs are removed and substituted in earlier passes." );
    272                 output << lineDirective( typeDecl );
    273250                output << "typedef ";
    274251                output << genType( typeDecl->get_base(), typeDecl->get_name(), pretty, genC ) << endl;
     
    285262                        } // if
    286263                } else {
    287                         output << typeDecl->genTypeString() << " " << typeDecl->get_name();
    288                         if ( typeDecl->get_kind() != TypeDecl::Any && typeDecl->get_sized() ) {
    289                                 output << " | sized(" << typeDecl->get_name() << ")";
    290                         }
     264                        output << typeDecl->typeString() << " " << typeDecl->get_name();
    291265                        if ( ! typeDecl->get_assertions().empty() ) {
    292266                                output << " | { ";
     
    342316        }
    343317
    344         // *** Expressions
     318        //*** Expressions
    345319        void CodeGenerator::visit( ApplicationExpr * applicationExpr ) {
    346320                extension( applicationExpr );
     
    745719        void CodeGenerator::visit( StmtExpr * stmtExpr ) {
    746720                std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids();
    747                 output << lineDirective( stmtExpr) << "({" << std::endl;
     721                output << "({" << std::endl;
    748722                cur_indent += CodeGenerator::tabsize;
    749723                unsigned int numStmts = stmts.size();
    750724                unsigned int i = 0;
    751725                for ( Statement * stmt : stmts ) {
    752                         output << lineDirective( stmt ) << indent;
    753             output << printLabels( stmt->get_labels() );
     726                        output << indent << printLabels( stmt->get_labels() );
    754727                        if ( i+1 == numStmts ) {
    755728                                // last statement in a statement expression needs to be handled specially -
     
    773746        }
    774747
    775         // *** Statements
     748        //*** Statements
    776749        void CodeGenerator::visit( CompoundStmt * compoundStmt ) {
    777750                std::list<Statement*> ks = compoundStmt->get_kids();
     
    796769        void CodeGenerator::visit( ExprStmt * exprStmt ) {
    797770                assert( exprStmt );
    798                 Expression * expr = exprStmt->get_expr();
    799                 if ( genC ) {
    800                         // cast the top-level expression to void to reduce gcc warnings.
    801                         expr = new CastExpr( expr );
    802                 }
     771                // cast the top-level expression to void to reduce gcc warnings.
     772                Expression * expr = new CastExpr( exprStmt->get_expr() );
    803773                expr->accept( *this );
    804774                output << ";";
     
    837807
    838808        void CodeGenerator::visit( IfStmt * ifStmt ) {
    839                 output << lineDirective( ifStmt );
    840809                output << "if ( ";
    841810                ifStmt->get_condition()->accept( *this );
     
    851820
    852821        void CodeGenerator::visit( SwitchStmt * switchStmt ) {
    853                 output << lineDirective( switchStmt );
    854822                output << "switch ( " ;
    855823                switchStmt->get_condition()->accept( *this );
     
    864832
    865833        void CodeGenerator::visit( CaseStmt * caseStmt ) {
    866                 output << lineDirective( caseStmt );
    867834                output << indent;
    868835                if ( caseStmt->isDefault()) {
  • src/CodeGen/Generate.cc

    r6250a312 r0f9bef3  
    2222#include "SynTree/Declaration.h"
    2323#include "CodeGenerator.h"
    24 #include "GenType.h"
    25 #include "SynTree/SynTree.h"
    26 #include "SynTree/Type.h"
    27 #include "SynTree/BaseSyntaxNode.h"
    28 // #include "Tuples/Tuples.h"
     24#include "Tuples/Tuples.h"
    2925
    3026using namespace std;
     
    4339                } // for
    4440        }
    45 
    46         void generate( BaseSyntaxNode * node, std::ostream & os ) {
    47                 if ( Type * type = dynamic_cast< Type * >( node ) ) {
    48                         os << CodeGen::genPrettyType( type, "" );
    49                 } else {
    50                         CodeGen::CodeGenerator cgv( os, true, false );
    51                         node->accept( cgv );
    52                 }
    53                 os << std::endl;
    54         }
    5541} // namespace CodeGen
    5642
  • src/CodeGen/Generate.h

    r6250a312 r0f9bef3  
    2525        /// Generates code. doIntrinsics determines if intrinsic functions are printed, pretty formats output nicely (e.g., uses unmangled names, etc.), generateC is true when the output must consist only of C code (allows some assertions, etc.)
    2626        void generate( std::list< Declaration* > translationUnit, std::ostream &os, bool doIntrinsics, bool pretty, bool generateC = false );
    27 
    28         /// Generate code for a single node -- helpful for debugging in gdb
    29         void generate( BaseSyntaxNode * node, std::ostream & os );
    3027} // namespace CodeGen
    3128
  • src/CodeTools/module.mk

    r6250a312 r0f9bef3  
    1515###############################################################################
    1616
    17 SRC += CodeTools/DeclStats.cc \
    18         CodeTools/TrackLoc.cc
     17SRC += CodeTools/DeclStats.cc
  • src/Common/utility.h

    r6250a312 r0f9bef3  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Fri May 5 11:03:00 2017
    13 // Update Count     : 32
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Dec 14 21:25:25 2016
     13// Update Count     : 31
    1414//
    1515
     
    322322        std::string filename;
    323323
    324     /// Create a new unset CodeLocation.
    325         CodeLocation()
     324        CodeLocation()
    326325                : linenumber( -1 )
    327326                , filename("")
    328327        {}
    329328
    330     /// Create a new CodeLocation with the given values.
    331329        CodeLocation( const char* filename, int lineno )
    332330                : linenumber( lineno )
    333331                , filename(filename ? filename : "")
    334332        {}
    335 
    336     bool isSet () const {
    337         return -1 != linenumber;
    338     }
    339 
    340     bool isUnset () const {
    341         return !isSet();
    342     }
    343 
    344         void unset () {
    345                 linenumber = -1;
    346                 filename = "";
    347         }
    348 
    349         // Use field access for set.
    350333};
    351334
    352335inline std::string to_string( const CodeLocation& location ) {
    353         return location.isSet() ? location.filename + ":" + std::to_string(location.linenumber) + " " : "";
     336        return location.linenumber >= 0 ? location.filename + ":" + std::to_string(location.linenumber) + " " : "";
    354337}
    355338#endif // _UTILITY_H
  • src/Concurrency/Keywords.cc

    r6250a312 r0f9bef3  
    246246        //=============================================================================================
    247247        void ConcurrentSueKeyword::visit(StructDecl * decl) {
    248                 Visitor::visit(decl);
    249248                if( decl->get_name() == type_name ) {
    250249                        assert( !type_decl );
     
    386385        //=============================================================================================
    387386        void MutexKeyword::visit(FunctionDecl* decl) {
    388                 Visitor::visit(decl);           
    389 
    390387                std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl );
    391388                if( mutexArgs.empty() ) return;
     
    405402
    406403        void MutexKeyword::visit(StructDecl* decl) {
    407                 Visitor::visit(decl);
    408 
    409404                if( decl->get_name() == "monitor_desc" ) {
    410405                        assert( !monitor_decl );
     
    509504        //=============================================================================================
    510505        void ThreadStarter::visit(FunctionDecl * decl) {
    511                 Visitor::visit(decl);
    512                
    513506                if( ! InitTweak::isConstructor(decl->get_name()) ) return;
    514507
  • src/GenPoly/InstantiateGeneric.cc

    r6250a312 r0f9bef3  
    233233                                } else {
    234234                                        // normalize possibly dtype-static parameter type
    235                                         out.push_back( new TypeExpr{
     235                                        out.push_back( new TypeExpr{ 
    236236                                                ScrubTyVars::scrubAll( paramType->get_type()->clone() ) } );
    237237                                        gt |= genericType::concrete;
     
    369369                                DeclMutator::addDeclaration( concDecl );
    370370                                insert( inst, typeSubs, concDecl );
    371                                 concDecl->acceptMutator( *this ); // recursively instantiate members
    372371                        }
    373372                        StructInstType *newInst = new StructInstType( inst->get_qualifiers(), concDecl->get_name() );
     
    424423                                DeclMutator::addDeclaration( concDecl );
    425424                                insert( inst, typeSubs, concDecl );
    426                                 concDecl->acceptMutator( *this ); // recursively instantiate members
    427425                        }
    428426                        UnionInstType *newInst = new UnionInstType( inst->get_qualifiers(), concDecl->get_name() );
  • src/GenPoly/PolyMutator.cc

    r6250a312 r0f9bef3  
    5050
    5151        Statement * PolyMutator::mutateStatement( Statement *stmt ) {
    52                 // don't want statements from outer CompoundStmts to be added to this CompoundStmt
    53                 ValueGuard< std::list< Statement* > > oldStmtsToAdd( stmtsToAdd );
    54                 ValueGuard< std::list< Statement* > > oldStmtsToAddAfter( stmtsToAddAfter );
    55                 ValueGuard< TypeSubstitution * > oldEnv( env );
    56                 stmtsToAdd.clear();
    57                 stmtsToAddAfter.clear();
    58 
    5952                Statement *newStmt = maybeMutate( stmt, *this );
    6053                if ( ! stmtsToAdd.empty() || ! stmtsToAddAfter.empty() ) {
     
    9083
    9184        Statement * PolyMutator::mutate(IfStmt *ifStmt) {
    92                 ifStmt->set_condition(  mutateExpression( ifStmt->get_condition() ) );
    9385                ifStmt->set_thenPart(  mutateStatement( ifStmt->get_thenPart() ) );
    9486                ifStmt->set_elsePart(  mutateStatement( ifStmt->get_elsePart() ) );
     87                ifStmt->set_condition(  mutateExpression( ifStmt->get_condition() ) );
    9588                return ifStmt;
    9689        }
    9790
    9891        Statement * PolyMutator::mutate(WhileStmt *whileStmt) {
     92                whileStmt->set_body(  mutateStatement( whileStmt->get_body() ) );
    9993                whileStmt->set_condition(  mutateExpression( whileStmt->get_condition() ) );
    100                 whileStmt->set_body(  mutateStatement( whileStmt->get_body() ) );
    10194                return whileStmt;
    10295        }
    10396
    10497        Statement * PolyMutator::mutate(ForStmt *forStmt) {
     98                forStmt->set_body(  mutateStatement( forStmt->get_body() ) );
    10599                mutateAll( forStmt->get_initialization(), *this );
    106100                forStmt->set_condition(  mutateExpression( forStmt->get_condition() ) );
    107101                forStmt->set_increment(  mutateExpression( forStmt->get_increment() ) );
    108                 forStmt->set_body(  mutateStatement( forStmt->get_body() ) );
    109102                return forStmt;
    110103        }
    111104
    112105        Statement * PolyMutator::mutate(SwitchStmt *switchStmt) {
     106                mutateStatementList( switchStmt->get_statements() );
    113107                switchStmt->set_condition( mutateExpression( switchStmt->get_condition() ) );
    114                 mutateStatementList( switchStmt->get_statements() );
    115108                return switchStmt;
    116109        }
    117110
    118111        Statement * PolyMutator::mutate(CaseStmt *caseStmt) {
     112                mutateStatementList( caseStmt->get_statements() );
    119113                caseStmt->set_condition(  mutateExpression( caseStmt->get_condition() ) );
    120                 mutateStatementList( caseStmt->get_statements() );
    121114                return caseStmt;
    122115        }
  • src/Makefile.in

    r6250a312 r0f9bef3  
    108108        CodeGen/driver_cfa_cpp-OperatorTable.$(OBJEXT) \
    109109        CodeTools/driver_cfa_cpp-DeclStats.$(OBJEXT) \
    110         CodeTools/driver_cfa_cpp-TrackLoc.$(OBJEXT) \
    111110        Concurrency/driver_cfa_cpp-Keywords.$(OBJEXT) \
    112111        Common/driver_cfa_cpp-SemanticError.$(OBJEXT) \
     
    389388        CodeGen/FixNames.cc CodeGen/FixMain.cc \
    390389        CodeGen/OperatorTable.cc CodeTools/DeclStats.cc \
    391         CodeTools/TrackLoc.cc Concurrency/Keywords.cc \
    392         Common/SemanticError.cc Common/UniqueName.cc \
    393         Common/DebugMalloc.cc Common/Assert.cc \
     390        Concurrency/Keywords.cc Common/SemanticError.cc \
     391        Common/UniqueName.cc Common/DebugMalloc.cc Common/Assert.cc \
    394392        ControlStruct/LabelGenerator.cc ControlStruct/LabelFixer.cc \
    395393        ControlStruct/MLEMutator.cc ControlStruct/Mutate.cc \
     
    547545        @: > CodeTools/$(DEPDIR)/$(am__dirstamp)
    548546CodeTools/driver_cfa_cpp-DeclStats.$(OBJEXT):  \
    549         CodeTools/$(am__dirstamp) CodeTools/$(DEPDIR)/$(am__dirstamp)
    550 CodeTools/driver_cfa_cpp-TrackLoc.$(OBJEXT):  \
    551547        CodeTools/$(am__dirstamp) CodeTools/$(DEPDIR)/$(am__dirstamp)
    552548Concurrency/$(am__dirstamp):
     
    847843        -rm -f CodeGen/driver_cfa_cpp-OperatorTable.$(OBJEXT)
    848844        -rm -f CodeTools/driver_cfa_cpp-DeclStats.$(OBJEXT)
    849         -rm -f CodeTools/driver_cfa_cpp-TrackLoc.$(OBJEXT)
    850845        -rm -f Common/driver_cfa_cpp-Assert.$(OBJEXT)
    851846        -rm -f Common/driver_cfa_cpp-DebugMalloc.$(OBJEXT)
     
    959954@AMDEP_TRUE@@am__include@ @am__quote@CodeGen/$(DEPDIR)/driver_cfa_cpp-OperatorTable.Po@am__quote@
    960955@AMDEP_TRUE@@am__include@ @am__quote@CodeTools/$(DEPDIR)/driver_cfa_cpp-DeclStats.Po@am__quote@
    961 @AMDEP_TRUE@@am__include@ @am__quote@CodeTools/$(DEPDIR)/driver_cfa_cpp-TrackLoc.Po@am__quote@
    962956@AMDEP_TRUE@@am__include@ @am__quote@Common/$(DEPDIR)/driver_cfa_cpp-Assert.Po@am__quote@
    963957@AMDEP_TRUE@@am__include@ @am__quote@Common/$(DEPDIR)/driver_cfa_cpp-DebugMalloc.Po@am__quote@
     
    12011195@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o CodeTools/driver_cfa_cpp-DeclStats.obj `if test -f 'CodeTools/DeclStats.cc'; then $(CYGPATH_W) 'CodeTools/DeclStats.cc'; else $(CYGPATH_W) '$(srcdir)/CodeTools/DeclStats.cc'; fi`
    12021196
    1203 CodeTools/driver_cfa_cpp-TrackLoc.o: CodeTools/TrackLoc.cc
    1204 @am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT CodeTools/driver_cfa_cpp-TrackLoc.o -MD -MP -MF CodeTools/$(DEPDIR)/driver_cfa_cpp-TrackLoc.Tpo -c -o CodeTools/driver_cfa_cpp-TrackLoc.o `test -f 'CodeTools/TrackLoc.cc' || echo '$(srcdir)/'`CodeTools/TrackLoc.cc
    1205 @am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) CodeTools/$(DEPDIR)/driver_cfa_cpp-TrackLoc.Tpo CodeTools/$(DEPDIR)/driver_cfa_cpp-TrackLoc.Po
    1206 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='CodeTools/TrackLoc.cc' object='CodeTools/driver_cfa_cpp-TrackLoc.o' libtool=no @AMDEPBACKSLASH@
    1207 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1208 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o CodeTools/driver_cfa_cpp-TrackLoc.o `test -f 'CodeTools/TrackLoc.cc' || echo '$(srcdir)/'`CodeTools/TrackLoc.cc
    1209 
    1210 CodeTools/driver_cfa_cpp-TrackLoc.obj: CodeTools/TrackLoc.cc
    1211 @am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT CodeTools/driver_cfa_cpp-TrackLoc.obj -MD -MP -MF CodeTools/$(DEPDIR)/driver_cfa_cpp-TrackLoc.Tpo -c -o CodeTools/driver_cfa_cpp-TrackLoc.obj `if test -f 'CodeTools/TrackLoc.cc'; then $(CYGPATH_W) 'CodeTools/TrackLoc.cc'; else $(CYGPATH_W) '$(srcdir)/CodeTools/TrackLoc.cc'; fi`
    1212 @am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) CodeTools/$(DEPDIR)/driver_cfa_cpp-TrackLoc.Tpo CodeTools/$(DEPDIR)/driver_cfa_cpp-TrackLoc.Po
    1213 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='CodeTools/TrackLoc.cc' object='CodeTools/driver_cfa_cpp-TrackLoc.obj' libtool=no @AMDEPBACKSLASH@
    1214 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1215 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o CodeTools/driver_cfa_cpp-TrackLoc.obj `if test -f 'CodeTools/TrackLoc.cc'; then $(CYGPATH_W) 'CodeTools/TrackLoc.cc'; else $(CYGPATH_W) '$(srcdir)/CodeTools/TrackLoc.cc'; fi`
    1216 
    12171197Concurrency/driver_cfa_cpp-Keywords.o: Concurrency/Keywords.cc
    12181198@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Concurrency/driver_cfa_cpp-Keywords.o -MD -MP -MF Concurrency/$(DEPDIR)/driver_cfa_cpp-Keywords.Tpo -c -o Concurrency/driver_cfa_cpp-Keywords.o `test -f 'Concurrency/Keywords.cc' || echo '$(srcdir)/'`Concurrency/Keywords.cc
  • src/Parser/parser.yy

    r6250a312 r0f9bef3  
    393393        | '(' compound_statement ')'                                            // GCC, lambda expression
    394394                { $$ = new ExpressionNode( build_valexpr( $2 ) ); }
    395         | primary_expression '{' argument_expression_list '}' // CFA
    396                 {
    397                         Token fn;
    398                         fn.str = new std::string( "?{}" );                      // location undefined - use location of '{'?
    399                         $$ = new ExpressionNode( new ConstructorExpr( build_func( new ExpressionNode( build_varref( fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) );
    400                 }
    401395        ;
    402396
     
    431425        | '(' type_name_no_function ')' '{' initializer_list comma_opt '}' // C99, compound-literal
    432426                { $$ = new ExpressionNode( build_compoundLiteral( $2, new InitializerNode( $5, true ) ) ); }
    433         | '^' primary_expression '{' argument_expression_list '}' // CFA
     427        | postfix_expression '{' argument_expression_list '}' // CFA
    434428                {
    435429                        Token fn;
    436                         fn.str = new string( "^?{}" );                          // location undefined
    437                         $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( fn ) ), (ExpressionNode *)( $2 )->set_last( $4 ) ) );
     430                        fn.str = new std::string( "?{}" );                      // location undefined - use location of '{'?
     431                        $$ = new ExpressionNode( new ConstructorExpr( build_func( new ExpressionNode( build_varref( fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) );
    438432                }
    439433        ;
     
    736730        | exception_statement
    737731        | asm_statement
     732        | '^' postfix_expression '{' argument_expression_list '}' ';' // CFA
     733                {
     734                        Token fn;
     735                        fn.str = new string( "^?{}" );                          // location undefined
     736                        $$ = new StatementNode( build_expr( new ExpressionNode( build_func( new ExpressionNode( build_varref( fn ) ), (ExpressionNode *)( $2 )->set_last( $4 ) ) ) ) );
     737                }
     738        ;
    738739
    739740labeled_statement:
  • src/ResolvExpr/AlternativeFinder.cc

    r6250a312 r0f9bef3  
    766766                        } // if
    767767                } // for
     768                // function may return struct or union value, in which case we need to add alternatives for implicit conversions to each of the anonymous members
     769                for ( const Alternative & alt : alternatives ) {
     770                        addAnonConversions( alt );
     771                }
    768772
    769773                candidates.clear();
     
    771775
    772776                findMinCost( candidates.begin(), candidates.end(), std::back_inserter( alternatives ) );
    773 
    774                 // function may return struct or union value, in which case we need to add alternatives for implicit
    775                 // conversions to each of the anonymous members, must happen after findMinCost since anon conversions
    776                 // are never the cheapest expression
    777                 for ( const Alternative & alt : alternatives ) {
    778                         addAnonConversions( alt );
    779                 }
    780777
    781778                if ( alternatives.empty() && targetType && ! targetType->isVoid() ) {
  • src/SymTab/Validate.cc

    r6250a312 r0f9bef3  
    240240                ReturnTypeFixer::fix( translationUnit ); // must happen before autogen
    241241                acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions
    242                 acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist
    243                 VerifyCtorDtorAssign::verify( translationUnit );  // must happen before autogen, because autogen examines existing ctor/dtors
    244242                Concurrency::applyKeywords( translationUnit );
    245243                autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecayPass
    246244                Concurrency::implementMutexFuncs( translationUnit );
    247245                Concurrency::implementThreadStarter( translationUnit );
     246                acceptAll( translationUnit, epc );
    248247                ReturnChecker::checkFunctionReturns( translationUnit );
    249248                compoundliteral.mutateDeclarationList( translationUnit );
    250249                acceptAll( translationUnit, pass3 );
     250                VerifyCtorDtorAssign::verify( translationUnit );
    251251                ArrayLength::computeLength( translationUnit );
    252252        }
     
    817817                                throw SemanticError( "Constructors, destructors, and assignment functions require at least one parameter ", funcDecl );
    818818                        }
    819                         PointerType * ptrType = dynamic_cast< PointerType * >( params.front()->get_type() );
    820                         if ( ! ptrType || ptrType->is_array() ) {
     819                        if ( ! dynamic_cast< PointerType * >( params.front()->get_type() ) ) {
    821820                                throw SemanticError( "First parameter of a constructor, destructor, or assignment function must be a pointer ", funcDecl );
    822821                        }
  • src/SynTree/BaseSyntaxNode.h

    r6250a312 r0f9bef3  
    1818
    1919#include "Common/utility.h"
    20 #include "Visitor.h"
    2120
    2221class BaseSyntaxNode {
    2322  public:
    2423        CodeLocation location;
    25 
    26         virtual void accept( Visitor & v ) = 0; // temporary -- needs to be here so that BaseSyntaxNode is polymorphic and can be dynamic_cast
    2724};
    2825
  • src/SynTree/Declaration.h

    r6250a312 r0f9bef3  
    204204
    205205        virtual std::string typeString() const;
    206         virtual std::string genTypeString() const;
    207206
    208207        virtual TypeDecl *clone() const { return new TypeDecl( *this ); }
  • src/SynTree/PointerType.cc

    r6250a312 r0f9bef3  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // PointerType.cc --
     7// PointerType.cc -- 
    88//
    99// Author           : Richard C. Bilson
     
    3838void PointerType::print( std::ostream &os, int indent ) const {
    3939        Type::print( os, indent );
    40         if ( ! is_array() ) {
    41                 os << "pointer to ";
    42         } else {
    43                 os << "decayed ";
    44                 if ( isStatic ) {
    45                         os << "static ";
    46                 } // if
    47                 if ( isVarLen ) {
    48                         os << "variable length array of ";
    49                 } else if ( dimension ) {
    50                         os << "array of ";
    51                         dimension->print( os, indent );
    52                         os << " ";
    53                 } // if
    54         }
     40        os << "pointer to ";
     41        if ( isStatic ) {
     42                os << "static ";
     43        } // if
     44        if ( isVarLen ) {
     45                os << "variable length array of ";
     46        } else if ( dimension ) {
     47                os << "array of ";
     48                dimension->print( os, indent );
     49        } // if
    5550        if ( base ) {
    5651                base->print( os, indent );
  • src/SynTree/SynTree.h

    r6250a312 r0f9bef3  
    2121#include <map>
    2222#include <iostream>
    23 
    24 class BaseSyntaxNode;
    2523
    2624class Declaration;
  • src/SynTree/Type.h

    r6250a312 r0f9bef3  
    247247        void set_isStatic( bool newValue ) { isStatic = newValue; }
    248248
    249         bool is_array() const { return isStatic || isVarLen || dimension; }
    250 
    251249        virtual PointerType *clone() const { return new PointerType( *this ); }
    252250        virtual void accept( Visitor & v ) { v.visit( this ); }
  • src/SynTree/TypeDecl.cc

    r6250a312 r0f9bef3  
    2929}
    3030
    31 std::string TypeDecl::genTypeString() const {
    32         static const std::string kindNames[] = { "otype", "dtype", "ftype", "ttype" };
    33         return kindNames[ kind ];
    34 }
    35 
    3631std::ostream & operator<<( std::ostream & os, const TypeDecl::Data & data ) {
    3732  return os << data.kind << ", " << data.isComplete;
  • src/SynTree/Visitor.h

    r6250a312 r0f9bef3  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed May  3 08:58:00 2017
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Feb  9 14:23:24 2017
    1313// Update Count     : 10
    1414//
     
    2626        virtual ~Visitor();
    2727  public:
    28         // visit: Default implementation of all functions visits the children
    29     // of the given syntax node, but performs no other action.
    30 
    3128        virtual void visit( ObjectDecl *objectDecl );
    3229        virtual void visit( FunctionDecl *functionDecl );
  • src/benchmark/CorCtxSwitch.c

    r6250a312 r0f9bef3  
    33#include <thread>
    44
    5 #include "bench.h"
     5#include <unistd.h>                                     // sysconf
     6#include <sys/times.h>                                  // times
     7#include <time.h>
    68
    7 coroutine GreatSuspender {};
     9inline unsigned long long int Time() {
     10    timespec ts;
     11    clock_gettime(
     12#if defined( __linux__ )
     13         CLOCK_THREAD_CPUTIME_ID,
     14#elif defined( __freebsd__ )
     15         CLOCK_PROF,
     16#elif defined( __solaris__ )
     17         CLOCK_HIGHRES,
     18#else
     19    #error uC++ : internal error, unsupported architecture
     20#endif
     21         &ts );
     22    return 1000000000LL * ts.tv_sec + ts.tv_nsec;
     23} // Time
     24
     25struct GreatSuspender {
     26        coroutine_desc __cor;
     27};
     28
     29DECL_COROUTINE(GreatSuspender);
    830
    931void ?{}( GreatSuspender * this ) {
     
    2446}
    2547
     48#ifndef N
     49#define N 100000000
     50#endif
     51
    2652int main() {
    2753        const unsigned int NoOfTimes = N;
  • src/benchmark/Makefile.am

    r6250a312 r0f9bef3  
    4444        @rm -f ./a.out
    4545
    46 sched-int:
    47         ${CC} ${AM_CFLAGS} ${CFLAGS} ${ccflags} @CFA_FLAGS@ -nodebug -lrt -DN=10000000 SchedInt.c
    48         @for number in 1 2 3 4 5 6 7 8 9 10; do \
    49                 ./a.out ; \
    50         done
    51         @rm -f ./a.out
    52 
    53 monitor:
    54         ${CC} ${AM_CFLAGS} ${CFLAGS} ${ccflags} @CFA_FLAGS@ -nodebug -lrt -DN=10000000 Monitor.c
    55         @for number in 1 2 3 4 5 6 7 8 9 10; do \
    56                 ./a.out ; \
    57         done
    58         @rm -f ./a.out
    59 
    6046csv-data:
    6147        @${CC} ${AM_CFLAGS} ${CFLAGS} ${ccflags} @CFA_FLAGS@ -nodebug -lrt -quiet -DN=10000000 csv-data.c
  • src/benchmark/Makefile.in

    r6250a312 r0f9bef3  
    492492        @rm -f ./a.out
    493493
    494 sched-int:
    495         ${CC} ${AM_CFLAGS} ${CFLAGS} ${ccflags} @CFA_FLAGS@ -nodebug -lrt -DN=10000000 SchedInt.c
    496         @for number in 1 2 3 4 5 6 7 8 9 10; do \
    497                 ./a.out ; \
    498         done
    499         @rm -f ./a.out
    500 
    501 monitor:
    502         ${CC} ${AM_CFLAGS} ${CFLAGS} ${ccflags} @CFA_FLAGS@ -nodebug -lrt -DN=10000000 Monitor.c
    503         @for number in 1 2 3 4 5 6 7 8 9 10; do \
    504                 ./a.out ; \
    505         done
    506         @rm -f ./a.out
    507 
    508494csv-data:
    509495        @${CC} ${AM_CFLAGS} ${CFLAGS} ${ccflags} @CFA_FLAGS@ -nodebug -lrt -quiet -DN=10000000 csv-data.c
  • src/benchmark/ThrdCtxSwitch.c

    r6250a312 r0f9bef3  
    33#include <thread>
    44
    5 #include "bench.h"
     5#include <unistd.h>                                     // sysconf
     6#include <sys/times.h>                                  // times
     7#include <time.h>
     8
     9inline unsigned long long int Time() {
     10    timespec ts;
     11    clock_gettime(
     12#if defined( __linux__ )
     13         CLOCK_THREAD_CPUTIME_ID,
     14#elif defined( __freebsd__ )
     15         CLOCK_PROF,
     16#elif defined( __solaris__ )
     17         CLOCK_HIGHRES,
     18#else
     19    #error uC++ : internal error, unsupported architecture
     20#endif
     21         &ts );
     22    return 1000000000LL * ts.tv_sec + ts.tv_nsec;
     23} // Time
     24 
     25#ifndef N
     26#define N 100000000
     27#endif
    628
    729int main() {
  • src/benchmark/bench.c

    r6250a312 r0f9bef3  
    44#include <thread>
    55
    6 #include "bench.h"
     6#include <unistd.h>                                     // sysconf
     7#include <sys/times.h>                                  // times
     8#include <time.h>
     9
     10inline unsigned long long int Time() {
     11    timespec ts;
     12    clock_gettime(
     13#if defined( __linux__ )
     14         CLOCK_THREAD_CPUTIME_ID,
     15#elif defined( __freebsd__ )
     16         CLOCK_PROF,
     17#elif defined( __solaris__ )
     18         CLOCK_HIGHRES,
     19#else
     20    #error uC++ : internal error, unsupported architecture
     21#endif
     22         &ts );
     23    return 1000000000LL * ts.tv_sec + ts.tv_nsec;
     24} // Time
    725
    826//=======================================
     
    6886//=======================================
    6987
    70 coroutine CoroutineDummy {};
     88struct CoroutineDummy { coroutine_desc __cor; };
     89DECL_COROUTINE(CoroutineDummy);
    7190void main(CoroutineDummy * this) {}
    7291
     
    98117}
    99118
    100 coroutine CoroutineResume {
     119struct CoroutineResume {
    101120    int N;
     121    coroutine_desc __cor;
    102122};
     123
     124DECL_COROUTINE(CoroutineResume);
    103125
    104126void ?{}(CoroutineResume* this, int N) {
     
    128150//=======================================
    129151
    130 thread ThreadDummy {};
     152struct ThreadDummy { thread_desc __thrd; };
     153DECL_THREAD(ThreadDummy);
    131154void main(ThreadDummy * this) {}
    132155
     
    154177}
    155178
    156 thread ContextSwitch {
     179struct ContextSwitch {
    157180    int N;
    158181    long long result;
     182    thread_desc __thrd;
    159183};
     184
     185DECL_THREAD(ContextSwitch);
    160186
    161187void main(ContextSwitch * this) {   
     
    215241        DynamicTaskCreateDelete( NoOfTimes );
    216242        {
    217                 ContextSwitch dummy = { (int)NoOfTimes };               // context switch
     243                scoped(ContextSwitch) dummy = { (int)NoOfTimes };               // context switch
    218244        }
    219245        sout | "\t" | endl;
  • src/benchmark/csv-data.c

    r6250a312 r0f9bef3  
    11#include <fstream>
    2 #include <monitor>
    32#include <stdlib>
    43#include <thread>
    54
    6 #include "bench.h"
     5extern "C" {
     6#include <unistd.h>                                     // sysconf
     7#include <sys/times.h>                                  // times
     8#include <time.h>
     9}
    710
    8 coroutine GreatSuspender {};
     11inline unsigned long long int Time() {
     12    timespec ts;
     13    clock_gettime(
     14#if defined( __linux__ )
     15         CLOCK_THREAD_CPUTIME_ID,
     16#elif defined( __freebsd__ )
     17         CLOCK_PROF,
     18#elif defined( __solaris__ )
     19         CLOCK_HIGHRES,
     20#else
     21    #error uC++ : internal error, unsupported architecture
     22#endif
     23         &ts );
     24    return 1000000000LL * ts.tv_sec + ts.tv_nsec;
     25} // Time
     26
     27struct GreatSuspender {
     28        coroutine_desc __cor;
     29};
     30
     31DECL_COROUTINE(GreatSuspender);
    932
    1033void ?{}( GreatSuspender * this ) {
     
    2952#endif
    3053
    31 //-----------------------------------------------------------------------------
    32 // coroutine context switch
     54
     55
    3356long long int measure_coroutine() {
    3457        const unsigned int NoOfTimes = N;
     
    4871}
    4972
    50 //-----------------------------------------------------------------------------
    51 // thread context switch
    5273long long int measure_thread() {
    5374        const unsigned int NoOfTimes = N;
     
    6384}
    6485
    65 //-----------------------------------------------------------------------------
    66 // single monitor entry
    67 monitor mon_t {};
    68 void dummy( mon_t * mutex m ) {}
    69 
    70 long long int measure_1_monitor_entry() {
    71         const unsigned int NoOfTimes = N;
    72         long long int StartTime, EndTime;
    73         mon_t mon;
    74 
    75         StartTime = Time();
    76         for ( volatile unsigned int i = 0; i < NoOfTimes; i += 1 ) {
    77                 dummy( &mon );
    78         }
    79         EndTime = Time();
    80 
    81         return ( EndTime - StartTime ) / NoOfTimes;
    82 }
    83 
    84 //-----------------------------------------------------------------------------
    85 // multi monitor entry
    86 void dummy( mon_t * mutex m1,  mon_t * mutex m2 ) {}
    87 
    88 long long int measure_2_monitor_entry() {
    89         const unsigned int NoOfTimes = N;
    90         long long int StartTime, EndTime;
    91         mon_t mon1, mon2;
    92 
    93         StartTime = Time();
    94         for ( volatile unsigned int i = 0; i < NoOfTimes; i += 1 ) {
    95                 dummy( &mon1, &mon2 );
    96         }
    97         EndTime = Time();
    98 
    99         return ( EndTime - StartTime ) / NoOfTimes;
    100 }
    101 
    102 //-----------------------------------------------------------------------------
    103 // single internal sched entry
    104 mon_t mon1;
    105 
    106 condition cond1a;
    107 condition cond1b;
    108 
    109 thread thrd1a { long long int * out; };
    110 thread thrd1b {};
    111 
    112 void ?{}( thrd1a * this, long long int * out ) {
    113         this->out = out;
    114 }
    115 
    116 void side1A( mon_t * mutex a, long long int * out ) {
    117         long long int StartTime, EndTime;
    118 
    119         StartTime = Time();
    120         for( int i = 0;; i++ ) {
    121                 signal(&cond1a);
    122                 if( i > N ) break;
    123                 wait(&cond1b);
    124         }
    125         EndTime = Time();
    126 
    127         *out = ( EndTime - StartTime ) / N;
    128 }
    129 
    130 void side1B( mon_t * mutex a ) {
    131         for( int i = 0;; i++ ) {
    132                 signal(&cond1b);
    133                 if( i > N ) break;
    134                 wait(&cond1a);
    135         }
    136 }
    137 
    138 void main( thrd1a * this ) { side1A( &mon1, this->out ); }
    139 void main( thrd1b * this ) { side1B( &mon1 ); }
    140 
    141 long long int measure_1_sched_int() {
    142         long long int t;
    143         {
    144                 thrd1a a = { &t };
    145                 thrd1b b;
    146         }
    147         return t;
    148 }
    149 
    150 //-----------------------------------------------------------------------------
    151 // multi internal sched entry
    152 mon_t mon2;
    153 
    154 condition cond2a;
    155 condition cond2b;
    156 
    157 thread thrd2a { long long int * out; };
    158 thread thrd2b {};
    159 
    160 void ?{}( thrd2a * this, long long int * out ) {
    161         this->out = out;
    162 }
    163 
    164 void side2A( mon_t * mutex a, mon_t * mutex b, long long int * out ) {
    165         long long int StartTime, EndTime;
    166 
    167         StartTime = Time();
    168         for( int i = 0;; i++ ) {
    169                 signal(&cond2a);
    170                 if( i > N ) break;
    171                 wait(&cond2b);
    172         }
    173         EndTime = Time();
    174 
    175         *out = ( EndTime - StartTime ) / N;
    176 }
    177 
    178 void side2B( mon_t * mutex a, mon_t * mutex b ) {
    179         for( int i = 0;; i++ ) {
    180                 signal(&cond2b);
    181                 if( i > N ) break;
    182                 wait(&cond2a);
    183         }
    184 }
    185 
    186 void main( thrd2a * this ) { side2A( &mon1, &mon2, this->out ); }
    187 void main( thrd2b * this ) { side2B( &mon1, &mon2 ); }
    188 
    189 long long int measure_2_sched_int() {
    190         long long int t;
    191         {
    192                 thrd2a a = { &t };
    193                 thrd2b b;
    194         }
    195         return t;
    196 }
    197 
    198 //-----------------------------------------------------------------------------
    199 // main loop
    20086int main()
    20187{
    202         sout | time(NULL) | ',';
    203         sout | measure_coroutine() | ',';
    204         sout | measure_thread() | ',';
    205         sout | measure_1_monitor_entry() | ',';
    206         sout | measure_2_monitor_entry() | ',';
    207         sout | measure_1_sched_int() | ',';
    208         sout | measure_2_sched_int() | endl;
     88        sout | time(NULL) | ',' | measure_coroutine() | ',' | measure_thread() | endl;
    20989}
  • src/libcfa/concurrency/monitor

    r6250a312 r0f9bef3  
    8181}
    8282
    83 static inline void ^?{}( condition * this ) {
    84         free( this->monitors );
    85 }
    86 
    8783void wait( condition * this );
    8884void signal( condition * this );
  • src/libcfa/concurrency/monitor.c

    r6250a312 r0f9bef3  
    1717#include "monitor"
    1818
    19 #include <stdlib>
    20 
    2119#include "kernel_private.h"
    2220#include "libhdr.h"
     
    132130        this_thread()->current_monitors      = this->prev_mntrs;
    133131        this_thread()->current_monitor_count = this->prev_count;
    134 }
    135 
    136 void debug_break() __attribute__(( noinline ))
    137 {
    138        
    139132}
    140133
     
    178171
    179172        //Find the next thread(s) to run
    180         unsigned short thread_count = 0;
     173        unsigned short thread_count = count;
    181174        thread_desc * threads[ count ];
    182         for(int i = 0; i < count; i++) {
    183                 threads[i] = 0;
    184         }
    185 
    186         debug_break();
    187175
    188176        for( int i = 0; i < count; i++) {
    189177                thread_desc * new_owner = next_thread( this->monitors[i] );
    190                 thread_count = insert_unique( threads, thread_count, new_owner );
    191         }
    192 
    193         debug_break();
     178                thread_count = insert_unique( threads, i, new_owner );
     179        }
    194180
    195181        LIB_DEBUG_PRINT_SAFE("Will unblock: ");
     
    353339                LIB_DEBUG_PRINT_SAFE("Branding\n");
    354340                assertf( thrd->current_monitors != NULL, "No current monitor to brand condition", thrd->current_monitors );
     341                this->monitors = thrd->current_monitors;
    355342                this->monitor_count = thrd->current_monitor_count;
    356 
    357                 this->monitors = malloc( this->monitor_count * sizeof( *this->monitors ) );
    358                 for( int i = 0; i < this->monitor_count; i++ ) {
    359                         this->monitors[i] = thrd->current_monitors[i];
    360                 }
    361343        }
    362344}
    363345
    364346static inline unsigned short insert_unique( thread_desc ** thrds, unsigned short end, thread_desc * val ) {
    365         if( !val ) return end;
    366 
    367         for(int i = 0; i <= end; i++) {
     347        for(int i = 0; i < end; i++) {
    368348                if( thrds[i] == val ) return end;
    369349        }
  • src/libcfa/concurrency/thread.c

    r6250a312 r0f9bef3  
    4040        this->next = NULL;
    4141
    42         this->current_monitors      = &this->mon;
    43         this->current_monitor_count = 1;
     42        this->current_monitors      = NULL;
     43        this->current_monitor_count = 0;
    4444}
    4545
  • src/libcfa/rational

    r6250a312 r0f9bef3  
    1212// Created On       : Wed Apr  6 17:56:25 2016
    1313// Last Modified By : Peter A. Buhr
    14 // Last Modified On : Mon May  1 08:25:06 2017
    15 // Update Count     : 33
     14// Last Modified On : Wed May  4 14:11:45 2016
     15// Update Count     : 16
    1616//
    17 
    1817#ifndef RATIONAL_H
    1918#define RATIONAL_H
     
    2221
    2322// implementation
    24 typedef long int RationalImpl;
    2523struct Rational {
    26         RationalImpl numerator, denominator;                                    // invariant: denominator > 0
     24        long int numerator, denominator;                                        // invariant: denominator > 0
    2725}; // Rational
    2826
     
    3331// constructors
    3432void ?{}( Rational * r );
    35 void ?{}( Rational * r, RationalImpl n );
    36 void ?{}( Rational * r, RationalImpl n, RationalImpl d );
     33void ?{}( Rational * r, long int n );
     34void ?{}( Rational * r, long int n, long int d );
    3735
    38 // getter for numerator/denominator
    39 RationalImpl numerator( Rational r );
    40 RationalImpl denominator( Rational r );
    41 [ RationalImpl, RationalImpl ] ?=?( * [ RationalImpl, RationalImpl ] dest, Rational src );
    42 // setter for numerator/denominator
    43 RationalImpl numerator( Rational r, RationalImpl n );
    44 RationalImpl denominator( Rational r, RationalImpl d );
     36// getter/setter for numerator/denominator
     37long int numerator( Rational r );
     38long int numerator( Rational r, long int n );
     39long int denominator( Rational r );
     40long int denominator( Rational r, long int d );
    4541
    4642// comparison
     
    6157// conversion
    6258double widen( Rational r );
    63 Rational narrow( double f, RationalImpl md );
     59Rational narrow( double f, long int md );
    6460
    6561// I/O
  • src/libcfa/rational.c

    r6250a312 r0f9bef3  
    1010// Created On       : Wed Apr  6 17:54:28 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Apr 27 17:05:06 2017
    13 // Update Count     : 51
     12// Last Modified On : Sat Jul  9 11:18:04 2016
     13// Update Count     : 40
    1414//
    1515
     
    3030// Calculate greatest common denominator of two numbers, the first of which may be negative. Used to reduce rationals.
    3131// alternative: https://en.wikipedia.org/wiki/Binary_GCD_algorithm
    32 static RationalImpl gcd( RationalImpl a, RationalImpl b ) {
     32static long int gcd( long int a, long int b ) {
    3333        for ( ;; ) {                                                                            // Euclid's algorithm
    34                 RationalImpl r = a % b;
     34                long int r = a % b;
    3535          if ( r == 0 ) break;
    3636                a = b;
     
    4040} // gcd
    4141
    42 static RationalImpl simplify( RationalImpl *n, RationalImpl *d ) {
     42static long int simplify( long int *n, long int *d ) {
    4343        if ( *d == 0 ) {
    4444                serr | "Invalid rational number construction: denominator cannot be equal to 0." | endl;
     
    5656} // rational
    5757
    58 void ?{}( Rational * r, RationalImpl n ) {
     58void ?{}( Rational * r, long int n ) {
    5959        r{ n, 1 };
    6060} // rational
    6161
    62 void ?{}( Rational * r, RationalImpl n, RationalImpl d ) {
    63         RationalImpl t = simplify( &n, &d );                            // simplify
     62void ?{}( Rational * r, long int n, long int d ) {
     63        long int t = simplify( &n, &d );                                        // simplify
    6464        r->numerator = n / t;
    6565        r->denominator = d / t;
     
    6767
    6868
    69 // getter for numerator/denominator
    70 
    71 RationalImpl numerator( Rational r ) {
     69// getter/setter for numerator/denominator
     70
     71long int numerator( Rational r ) {
    7272        return r.numerator;
    7373} // numerator
    7474
    75 RationalImpl denominator( Rational r ) {
    76         return r.denominator;
    77 } // denominator
    78 
    79 [ RationalImpl, RationalImpl ] ?=?( * [ RationalImpl, RationalImpl ] dest, Rational src ) {
    80         return *dest = src.[ numerator, denominator ];
    81 }
    82 
    83 // setter for numerator/denominator
    84 
    85 RationalImpl numerator( Rational r, RationalImpl n ) {
    86         RationalImpl prev = r.numerator;
    87         RationalImpl t = gcd( abs( n ), r.denominator );                // simplify
     75long int numerator( Rational r, long int n ) {
     76        long int prev = r.numerator;
     77        long int t = gcd( abs( n ), r.denominator );            // simplify
    8878        r.numerator = n / t;
    8979        r.denominator = r.denominator / t;
     
    9181} // numerator
    9282
    93 RationalImpl denominator( Rational r, RationalImpl d ) {
    94         RationalImpl prev = r.denominator;
    95         RationalImpl t = simplify( &r.numerator, &d );                  // simplify
     83long int denominator( Rational r ) {
     84        return r.denominator;
     85} // denominator
     86
     87long int denominator( Rational r, long int d ) {
     88        long int prev = r.denominator;
     89        long int t = simplify( &r.numerator, &d );                      // simplify
    9690        r.numerator = r.numerator / t;
    9791        r.denominator = d / t;
     
    176170
    177171// http://www.ics.uci.edu/~eppstein/numth/frap.c
    178 Rational narrow( double f, RationalImpl md ) {
     172Rational narrow( double f, long int md ) {
    179173        if ( md <= 1 ) {                                                                        // maximum fractional digits too small?
    180174                return (Rational){ f, 1};                                               // truncate fraction
     
    182176
    183177        // continued fraction coefficients
    184         RationalImpl m00 = 1, m11 = 1, m01 = 0, m10 = 0;
    185         RationalImpl ai, t;
     178        long int m00 = 1, m11 = 1, m01 = 0, m10 = 0;
     179        long int ai, t;
    186180
    187181        // find terms until denom gets too big
    188182        for ( ;; ) {
    189                 ai = (RationalImpl)f;
     183                ai = (long int)f;
    190184          if ( ! (m10 * ai + m11 <= md) ) break;
    191185                t = m00 * ai + m01;
     
    208202forall( dtype istype | istream( istype ) )
    209203istype * ?|?( istype *is, Rational *r ) {
    210         RationalImpl t;
     204        long int t;
    211205        is | &(r->numerator) | &(r->denominator);
    212206        t = simplify( &(r->numerator), &(r->denominator) );
  • src/main.cc

    r6250a312 r0f9bef3  
    3737#include "CodeGen/FixMain.h"
    3838#include "CodeTools/DeclStats.h"
    39 #include "CodeTools/TrackLoc.h"
    4039#include "ControlStruct/Mutate.h"
    4140#include "SymTab/Validate.h"
     
    309308                } // if
    310309
    311                 CodeTools::fillLocations( translationUnit );
    312310                CodeGen::generate( translationUnit, *output, ! noprotop, prettycodegenp, true );
    313311
  • src/tests/Makefile.am

    r6250a312 r0f9bef3  
    2222concurrent=yes
    2323quick_test+= coroutine thread monitor
    24 concurrent_test=coroutine thread monitor multi-monitor sched-int-disjoint sched-int-barge sched-int-wait sched-ext sched-ext-multi preempt
     24concurrent_test=coroutine thread monitor multi-monitor sched-int sched-ext preempt
    2525else
    2626concurrent=no
  • src/tests/Makefile.in

    r6250a312 r0f9bef3  
    230230@BUILD_CONCURRENCY_TRUE@concurrent = yes
    231231@BUILD_CONCURRENCY_FALSE@concurrent_test =
    232 @BUILD_CONCURRENCY_TRUE@concurrent_test = coroutine thread monitor multi-monitor sched-int-disjoint sched-int-barge sched-int-wait sched-ext sched-ext-multi preempt
     232@BUILD_CONCURRENCY_TRUE@concurrent_test = coroutine thread monitor multi-monitor sched-int sched-ext preempt
     233TEST_FLAGS = $(if $(test), 2> .err/${@}.log, )
    233234
    234235# applies to both programs
    235236EXTRA_FLAGS =
    236237BUILD_FLAGS = -g -Wall -Wno-unused-function @CFA_FLAGS@ ${EXTRA_FLAGS}
    237 TEST_FLAGS = $(if $(test), 2> .err/${@}.log, )
    238238fstream_test_SOURCES = fstream_test.c
    239239vector_test_SOURCES = vector/vector_int.c vector/array.c vector/vector_test.c
  • src/tests/rational.c

    r6250a312 r0f9bef3  
    1010// Created On       : Mon Mar 28 08:43:12 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May  2 22:11:05 2017
    13 // Update Count     : 41
     12// Last Modified On : Tue Jul  5 18:29:37 2016
     13// Update Count     : 25
    1414//
    1515
     
    3636        b = (Rational){ -3, 2 };
    3737        sout | a | b | endl;
    38 //      sout | a == 1 | endl; // FIX ME
     38        sout | a == 1 | endl;
    3939        sout | a != b | endl;
    4040        sout | a <  b | endl;
     
    6161        sout | narrow( 3.14159265358979, 256 ) | endl;
    6262
    63         sout | "decompose" | endl;
    64         RationalImpl n, d;
    65 //      [n, d] = a;
    66 //      sout | a | n | d | endl;
    67 
    68         sout | "more tests" | endl;
    6963        Rational x = { 1, 2 }, y = { 2 };
    7064        sout | x - y | endl;
Note: See TracChangeset for help on using the changeset viewer.