Changeset 86fb8f2


Ignore:
Timestamp:
Mar 27, 2019, 11:09:23 AM (6 years ago)
Author:
tdelisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
a45fc7b
Parents:
2b10f95 (diff), 1e5d0f0c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Files:
2 added
18 edited

Legend:

Unmodified
Added
Removed
  • doc/papers/concurrency/Paper.tex

    r2b10f95 r86fb8f2  
    654654\centering
    655655\newbox\myboxA
     656% \begin{lrbox}{\myboxA}
     657% \begin{cfa}[aboveskip=0pt,belowskip=0pt]
     658% `int fn1, fn2, state = 1;`   // single global variables
     659% int fib() {
     660%       int fn;
     661%       `switch ( state )` {  // explicit execution state
     662%         case 1: fn = 0;  fn1 = fn;  state = 2;  break;
     663%         case 2: fn = 1;  fn2 = fn1;  fn1 = fn;  state = 3;  break;
     664%         case 3: fn = fn1 + fn2;  fn2 = fn1;  fn1 = fn;  break;
     665%       }
     666%       return fn;
     667% }
     668% int main() {
     669%
     670%       for ( int i = 0; i < 10; i += 1 ) {
     671%               printf( "%d\n", fib() );
     672%       }
     673% }
     674% \end{cfa}
     675% \end{lrbox}
    656676\begin{lrbox}{\myboxA}
    657677\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    658 `int fn1, fn2, state = 1;`   // single global variables
    659 int fib() {
    660         int fn;
    661         `switch ( state )` {  // explicit execution state
    662           case 1: fn = 0;  fn1 = fn;  state = 2;  break;
    663           case 2: fn = 1;  fn2 = fn1;  fn1 = fn;  state = 3;  break;
    664           case 3: fn = fn1 + fn2;  fn2 = fn1;  fn1 = fn;  break;
    665         }
    666         return fn;
    667 }
     678#define FIB_INIT { 0, 1 }
     679typedef struct { int fn1, fn; } Fib;
     680int fib( Fib * f ) {
     681
     682        int ret = f->fn1;
     683        f->fn1 = f->fn;
     684        f->fn = ret + f->fn;
     685        return ret;
     686}
     687
     688
     689
    668690int main() {
    669 
     691        Fib f1 = FIB_INIT, f2 = FIB_INIT;
    670692        for ( int i = 0; i < 10; i += 1 ) {
    671                 printf( "%d\n", fib() );
     693                printf( "%d %d\n",
     694                                fib( &f1 ), fib( &f2 ) );
    672695        }
    673696}
     
    678701\begin{lrbox}{\myboxB}
    679702\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    680 #define FIB_INIT `{ 0, 1 }`
    681 typedef struct { int fn2, fn1; } Fib;
    682 int fib( Fib * f ) {
    683 
    684         int ret = f->fn2;
    685         int fn = f->fn1 + f->fn2;
    686         f->fn2 = f->fn1; f->fn1 = fn;
    687 
    688         return ret;
    689 }
    690 int main() {
    691         Fib f1 = FIB_INIT, f2 = FIB_INIT;
    692         for ( int i = 0; i < 10; i += 1 ) {
    693                 printf( "%d %d\n", fib( &fn1 ), fib( &f2 ) );
     703`coroutine` Fib { int fn1; };
     704void main( Fib & fib ) with( fib ) {
     705        int fn;
     706        [fn1, fn] = [0, 1];
     707        for () {
     708                `suspend();`
     709                [fn1, fn] = [fn, fn1 + fn];
    694710        }
    695711}
    696 \end{cfa}
    697 \end{lrbox}
    698 
    699 \subfloat[3 states: global variables]{\label{f:GlobalVariables}\usebox\myboxA}
    700 \qquad
    701 \subfloat[1 state: encapsulated variables]{\label{f:ExternalState}\usebox\myboxB}
    702 \caption{C fibonacci fsm}
    703 \label{f:C-fibonacci}
    704 
    705 \bigskip
    706 
    707 \newbox\myboxA
    708 \begin{lrbox}{\myboxA}
    709 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    710 `coroutine` Fib { int fn; };
    711 void main( Fib & fib ) with( fib ) {
    712         fn = 0;  int fn1 = fn; `suspend()`;
    713         fn = 1;  int fn2 = fn1;  fn1 = fn; `suspend()`;
    714         for () {
    715                 fn = fn1 + fn2; fn2 = fn1; fn1 = fn; `suspend()`; }
    716 }
    717 int next( Fib & fib ) with( fib ) { `resume( fib );` return fn; }
     712int ?()( Fib & fib ) with( fib ) {
     713        `resume( fib );`  return fn1;
     714}
    718715int main() {
    719716        Fib f1, f2;
    720         for ( 10 )
    721                 sout | next( f1 ) | next( f2 );
    722 }
     717        for ( 10 ) {
     718                sout | f1() | f2();
     719}
     720
     721
    723722\end{cfa}
    724723\end{lrbox}
    725 \newbox\myboxB
    726 \begin{lrbox}{\myboxB}
     724
     725\newbox\myboxC
     726\begin{lrbox}{\myboxC}
    727727\begin{python}[aboveskip=0pt,belowskip=0pt]
    728728
    729 def Fibonacci():
    730         fn = 0; fn1 = fn; `yield fn`  # suspend
    731         fn = 1; fn2 = fn1; fn1 = fn; `yield fn`
    732         while True:
    733                 fn = fn1 + fn2; fn2 = fn1; fn1 = fn; `yield fn`
    734 
    735 
    736 f1 = Fibonacci()
    737 f2 = Fibonacci()
     729def Fib():
     730
     731    fn1, fn = 0, 1
     732    while True:
     733        `yield fn1`
     734        fn1, fn = fn, fn1 + fn
     735
     736
     737// next prewritten
     738
     739
     740f1 = Fib()
     741f2 = Fib()
    738742for i in range( 10 ):
    739         print( `next( f1 )`, `next( f2 )` ) # resume
     743        print( next( f1 ), next( f2 ) )
     744
     745
    740746
    741747\end{python}
    742748\end{lrbox}
    743 \subfloat[\CFA]{\label{f:Coroutine3States}\usebox\myboxA}
    744 \qquad
    745 \subfloat[Python]{\label{f:Coroutine1State}\usebox\myboxB}
    746 \caption{Fibonacci input coroutine, 3 states, internal variables}
    747 \label{f:cfa-fibonacci}
     749
     750\subfloat[C]{\label{f:GlobalVariables}\usebox\myboxA}
     751\hspace{3pt}
     752\vrule
     753\hspace{3pt}
     754\subfloat[\CFA]{\label{f:ExternalState}\usebox\myboxB}
     755\hspace{3pt}
     756\vrule
     757\hspace{3pt}
     758\subfloat[Python]{\label{f:ExternalState}\usebox\myboxC}
     759\caption{Fibonacci Generator}
     760\label{f:C-fibonacci}
     761
     762% \bigskip
     763%
     764% \newbox\myboxA
     765% \begin{lrbox}{\myboxA}
     766% \begin{cfa}[aboveskip=0pt,belowskip=0pt]
     767% `coroutine` Fib { int fn; };
     768% void main( Fib & fib ) with( fib ) {
     769%       fn = 0;  int fn1 = fn; `suspend()`;
     770%       fn = 1;  int fn2 = fn1;  fn1 = fn; `suspend()`;
     771%       for () {
     772%               fn = fn1 + fn2; fn2 = fn1; fn1 = fn; `suspend()`; }
     773% }
     774% int next( Fib & fib ) with( fib ) { `resume( fib );` return fn; }
     775% int main() {
     776%       Fib f1, f2;
     777%       for ( 10 )
     778%               sout | next( f1 ) | next( f2 );
     779% }
     780% \end{cfa}
     781% \end{lrbox}
     782% \newbox\myboxB
     783% \begin{lrbox}{\myboxB}
     784% \begin{python}[aboveskip=0pt,belowskip=0pt]
     785%
     786% def Fibonacci():
     787%       fn = 0; fn1 = fn; `yield fn`  # suspend
     788%       fn = 1; fn2 = fn1; fn1 = fn; `yield fn`
     789%       while True:
     790%               fn = fn1 + fn2; fn2 = fn1; fn1 = fn; `yield fn`
     791%
     792%
     793% f1 = Fibonacci()
     794% f2 = Fibonacci()
     795% for i in range( 10 ):
     796%       print( `next( f1 )`, `next( f2 )` ) # resume
     797%
     798% \end{python}
     799% \end{lrbox}
     800% \subfloat[\CFA]{\label{f:Coroutine3States}\usebox\myboxA}
     801% \qquad
     802% \subfloat[Python]{\label{f:Coroutine1State}\usebox\myboxB}
     803% \caption{Fibonacci input coroutine, 3 states, internal variables}
     804% \label{f:cfa-fibonacci}
    748805\end{figure}
    749806
  • doc/papers/concurrency/examples/Pingpong.cfa

    r2b10f95 r86fb8f2  
    44coroutine PingPong {
    55        const char * name;
    6         /* const */ unsigned int N;
    7         PingPong * part;
     6        unsigned int N;
     7        PingPong & part;
    88};
    99
    1010void ?{}( PingPong & this, const char * name, unsigned int N, PingPong & part ) {
    11         (this.__cor){name};
    12         this.name = name;
    13         this.N = N;
    14         this.part = &part;
     11        this.[name, N] = [name, N];  &this.part = &part;
    1512}
    1613void ?{}( PingPong & this, const char * name, unsigned int N ) {
    17         this{ name, N, *(PingPong *)0 };
     14        this{ name, N, *0p };                                                           // call first constructor
    1815}
    1916void cycle( PingPong & pingpong ) {
     
    2118}
    2219void partner( PingPong & this, PingPong & part ) {
    23         this.part = &part;
     20        &this.part = &part;
    2421        resume( this );
    2522}
    26 void main( PingPong & pingpong ) {                                              // ping's starter ::main, pong's starter ping
    27         for ( pingpong.N ) {                                                            // N ping-pongs
    28                 sout | pingpong.name;
    29                 cycle( *pingpong.part );
     23void main( PingPong & pingpong ) with(pingpong) {               // ping's starter ::main, pong's starter ping
     24        for ( N ) {                                                                                     // N ping-pongs
     25                sout | name;
     26                cycle( part );
    3027        } // for
    3128}
    3229int main() {
    33         enum { N = 20 };
     30        enum { N = 5 };
    3431        PingPong ping = { "ping", N }, pong = { "pong", N, ping };
    3532        partner( ping, pong );
     
    3835// Local Variables: //
    3936// tab-width: 4 //
    40 // compile-command: "cfa pingpong.cfa" //
     37// compile-command: "cfa Pingpong.cfa" //
    4138// End: //
  • doc/papers/concurrency/examples/Pingpong.py

    r2b10f95 r86fb8f2  
    1 def Scheduler
     1def PingPong( name, N ):
     2        partner = (yield)           # get partner
     3        yield                       # resume scheduler
     4        for i in range( N ):
     5                print( name )
     6                yield partner           # execute next
     7        print( "end", name )
     8
     9def Scheduler():
     10        n = (yield)                 # starting coroutine
     11        while True:
     12                n = next( n )           # schedule coroutine
     13
     14pi = PingPong( "ping", 5 )
     15po = PingPong( "pong", 5 )
     16next( pi )                      # prime
     17pi.send( po )                   # send partner
     18next( po )                      # prime
     19po.send( pi )                   # send partner
     20
     21s = Scheduler();
     22next( s )                       # prime
    223try:
    3         yield from ping();
    4         yield from pong();
     24        s.send( pi )                            # start cycle
    525except StopIteration:
    6         print( "Scheduler stop" )
    7 
    8 
    9 def pong():
    10         print( "pong" )
    11 for i in range( 10 ):
    12 
    13                 yield from ping()
    14         print( "stop pong" )
    15 
    16 def ping():
    17         global i
    18         print( "ping" )
    19         i += 1
    20         if i < 5:
    21                 yield from pong()
    22         print( "stop ping" )
    23 
    24 p = ping()
    25 try:
    26         next( p )
    27 except StopIteration:
    28         print( "stop" )
     26        print( "scheduler stop" )
     27print( "stop" )
    2928
    3029# Local Variables: #
    3130# tab-width: 4 #
    32 # compile-command: "python3.5 pingpong.py" #
     31# compile-command: "python3.5 Pingpong.py" #
    3332# End: #
  • doc/papers/concurrency/examples/ProdCons.cfa

    r2b10f95 r86fb8f2  
    2323        sout | "prod stops";
    2424}
    25 int payment( Prod & prod, int money ) {
    26         prod.money = money;
     25int payment( Prod & prod, int m ) with(prod) {
     26        money = m;
    2727        resume( prod );                                                                         // main 1st time, then
    28         return prod.receipt;                                                            // prod in delivery
     28        return receipt;                                                                         // prod in delivery
    2929}
    3030void start( Prod & prod, int N, Cons &c ) {
  • doc/papers/concurrency/examples/ProdCons.cpp

    r2b10f95 r86fb8f2  
    1212struct Cons;
    1313
    14 struct Prod {
     14struct resumable {
     15        virtual resumable * resume() = 0;
     16};
     17
     18struct Prod : public resumable {
    1519        struct local {
    1620                Cons * c;
     
    2024        struct promise_type {
    2125                local _l;
     26                resumable * next;
    2227
    2328                Prod get_return_object() {
     
    6974        static Prod main();
    7075
    71         auto payment(int money) {
    72                 _coroutine.promise()._l.money = money;
    73                 struct ret {
    74                         int _receipt;
    75                         bool await_ready() { return false; }
    76                         void await_suspend(std::experimental::coroutine_handle<>) {}
    77                         int await_resume() { return _receipt; }
    78                 };
    79                 return ret{ _coroutine.promise()._l.receipt };
    80         }
     76        struct payment_return;
     77
     78        payment_return payment(int money);
    8179
    8280        auto start(int N, Cons & c) {
     
    8482                _coroutine.promise()._l.N = N;
    8583                _coroutine.promise()._l.receipt = 0;
     84        }
     85
     86        virtual resumable * resume() override final {
    8687                _coroutine.resume();
    87         }
    88 };
    89 
    90 struct Cons {
     88                return _coroutine.promise().next;
     89        }
     90};
     91
     92struct Cons : public resumable {
    9193        struct local {
    9294                Prod * p;
     
    9799        struct promise_type {
    98100                local _l;
     101                resumable * next;
    99102
    100103                Cons get_return_object() {
     
    154157                struct ret {
    155158                        int _status;
     159                        Cons * c;
    156160                        bool await_ready() { return false; }
    157                         void await_suspend(std::experimental::coroutine_handle<>) {}
     161                        void await_suspend(std::experimental::coroutine_handle<Prod::promise_type> _coroutine) {
     162                                _coroutine.promise().next = c;
     163                        }
    158164                        int await_resume() { return _status; }
    159165                };
    160                 return ret{ _coroutine.promise()._l.status };
     166                return ret{ _coroutine.promise()._l.status, this };
    161167        }
    162168
     
    164170                _coroutine.promise()._l.done = true;
    165171                struct ret {
     172                        Cons * c;
     173                        Prod::promise_type * _promise;
    166174                        bool await_ready() { return false; }
    167                         void await_suspend(std::experimental::coroutine_handle<>) {}
    168                         void await_resume() {}
     175                        void await_suspend(std::experimental::coroutine_handle<Prod::promise_type> _coroutine) {
     176                                _promise = &_coroutine.promise();
     177                                _promise->next = c;
     178                        }
     179                        void await_resume() {
     180                                _promise->next = nullptr;
     181                        }
    169182                };
    170                 return ret{};
    171         }
    172 };
     183                return ret{this, nullptr};
     184        }
     185
     186        virtual resumable * resume() override final {
     187                _coroutine.resume();
     188                return _coroutine.promise().next;
     189        }
     190};
     191
     192struct Prod::payment_return {
     193        int _receipt;
     194        Prod * p;
     195        bool await_ready() { return false; }
     196        void await_suspend(std::experimental::coroutine_handle<Cons::promise_type> _coroutine) {
     197                _coroutine.promise().next = p;
     198        }
     199        int await_resume() { return _receipt; }
     200};
     201
     202Prod::payment_return Prod::payment(int money)  {
     203        _coroutine.promise()._l.money = money;
     204        return payment_return{ _coroutine.promise()._l.receipt, this };
     205}
    173206
    174207Prod Prod::main() {
     
    176209        for(int i = 0; i < p.N; i++) {
    177210                int p1 = random(100), p2 = random(100);
    178                 std::cout << p1 << " " << p2;
     211                std::cout << p1 << " " << p2 << std::endl;
    179212                int status = co_await p.c->deliver(p1, p2);
    180                 std::cout << " $" << p.money << std::endl << status;
     213                std::cout << " $" << p.money << std::endl << status << std::endl;
    181214                p.receipt += 1;
    182215        }
    183216        co_await p.c->stop();
    184         std::cout << "prod stops";
     217        std::cout << "prod stops" << std::endl;
    185218}
    186219
     
    189222        int money = 1, receipt;
    190223        for(;!c.done ;) {
    191                 std::cout << c.p1 << " " << c.p2 << std::endl << " $" << money;
     224                std::cout << c.p1 << " " << c.p2 << std::endl;
     225                std::cout << " $ " << money << std::endl;
    192226                c.status += 1;
    193227                receipt = co_await c.p->payment( money );
    194                 std::cout << " #" << receipt;
     228                std::cout << " # " << receipt << std::endl;
    195229                money += 1;
    196230        }
    197         std::cout << "const stops";
     231        std::cout << "cons stops" << std::endl;
     232}
     233
     234void dispatch(resumable * r) {
     235        while((r = r->resume()));
    198236}
    199237
     
    203241        srandom( getpid() );
    204242        prod.start(5, cons);
    205 }
     243        dispatch(&prod);
     244}
  • doc/user/user.tex

    r2b10f95 r86fb8f2  
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Tue Dec 11 23:19:26 2018
    14 %% Update Count     : 3400
     13%% Last Modified On : Tue Mar 26 22:10:49 2019
     14%% Update Count     : 3411
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    508508
    509509As for \Index{division}, there are exponentiation operators for integral and floating types, including the builtin \Index{complex} types.
    510 Unsigned integral exponentiation\index{exponentiation!unsigned integral} is performed with repeated multiplication\footnote{The multiplication computation is $O(\log y)$.} (or shifting if the base is 2).
    511 Signed integral exponentiation\index{exponentiation!signed integral} is performed with repeated multiplication (or shifting if the base is 2), but yields a floating result because $x^{-y}=1/x^y$.
    512 Hence, it is important to designate exponent integral-constants as unsigned or signed: ©3 \ 3u© return an integral result, while ©3 \ 3© returns a floating result.
    513 Floating exponentiation\index{exponentiation!floating} is performed using \Index{logarithm}s\index{exponentiation!logarithm}, so the base cannot be negative.
    514 \begin{cfa}
    515 sout | 2 ®\® 8u | 4 ®\® 3u | -4 ®\® 3u | 4 ®\® -3 | -4 ®\® -3 | 4.0 ®\® 2.1 | (1.0f+2.0fi) ®\® (3.0f+2.0fi);
    516 256 64 -64 0.015625 -0.015625 18.3791736799526 0.264715-1.1922i
     510Integral exponentiation\index{exponentiation!unsigned integral} is performed with repeated multiplication\footnote{The multiplication computation is $O(\log y)$.} (or shifting if the exponent is 2).
     511Overflow from large exponents or negative exponents return zero.
     512Floating exponentiation\index{exponentiation!floating} is performed using \Index{logarithm}s\index{exponentiation!logarithm}, so the exponent cannot be negative.
     513\begin{cfa}
     514sout | 1 ®\® 0 | 1 ®\® 1 | 2 ®\® 8 | -4 ®\® 3 | 5 ®\® 3 | 5 ®\® 32 | 5L ®\® 32 | 5L ®\® 64 | -4 ®\® -3 | -4.0 ®\® -3 | 4.0 ®\® 2.1
     515          | (1.0f+2.0fi) ®\® (3.0f+2.0fi);
     5161 1 256 -64 125 0 3273344365508751233 0 0 -0.015625 18.3791736799526 0.264715-1.1922i
    517517\end{cfa}
    518518Parenthesis are necessary for complex constants or the expression is parsed as ©1.0f+®(®2.0fi \ 3.0f®)®+2.0fi©.
    519 The exponentiation operator is available for all the basic types, but for user-defined types, only the integral-computation versions are available.
    520 For returning an integral value, the user type ©T© must define multiplication, ©*©, and one, ©1©;
    521 for returning a floating value, an additional divide of type ©T© into a ©double© returning a ©double© (©double ?/?( double, T )©) is necessary for negative exponents.
     519The exponentiation operator is available for all the basic types, but for user-defined types, only the integral-computation version is available.
     520\begin{cfa}
     521forall( otype OT | { void ?{}( OT & this, one_t ); OT ?*?( OT, OT ); } )
     522OT ?®\®?( OT ep, unsigned int y );
     523forall( otype OT | { void ?{}( OT & this, one_t ); OT ?*?( OT, OT ); } )
     524OT ?®\®?( OT ep, unsigned long int y );
     525\end{cfa}
     526The user type ©T© must define multiplication one, ©1©, and, ©*©.
    522527
    523528
     
    13201325\end{cfa}
    13211326Essentially, the return type is wrapped around the routine name in successive layers (like an \Index{onion}).
    1322 While attempting to make the two contexts consistent is a laudable goal, it has not worked out in practice.
     1327While attempting to make the two contexts consistent is a laudable goal, it has not worked out in practice, even though Dennis Richie believed otherwise:
     1328\begin{quote}
     1329In spite of its difficulties, I believe that the C's approach to declarations remains plausible, and am comfortable with it; it is a useful unifying principle.~\cite[p.~12]{Ritchie93}
     1330\end{quote}
    13231331
    13241332\CFA provides its own type, variable and routine declarations, using a different syntax.
  • libcfa/prelude/builtins.c

    r2b10f95 r86fb8f2  
    1010// Created On       : Fri Jul 21 16:21:03 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Mar 10 10:52:50 2019
    13 // Update Count     : 31
     12// Last Modified On : Tue Mar 26 23:10:36 2019
     13// Update Count     : 95
    1414//
    1515
     
    1818typedef unsigned long long __cfaabi_abi_exception_type_t;
    1919
     20#include <limits.h>                                                                             // CHAR_BIT
    2021#include "../src/virtual.h"
    2122#include "../src/exception.h"
     
    2627// increment/decrement unification
    2728
    28 static inline forall( dtype T | { T & ?+=?( T &, one_t ); } )
    29 T & ++? ( T & x ) { return x += 1; }
     29static inline {
     30        forall( dtype DT | { DT & ?+=?( DT &, one_t ); } )
     31        DT & ++?( DT & x ) { return x += 1; }
    3032
    31 static inline forall( dtype T | sized(T) | { void ?{}( T &, T ); void ^?{}( T & ); T & ?+=?( T &, one_t ); } )
    32 T & ?++ ( T & x ) { T tmp = x; x += 1; return tmp; }
     33        forall( dtype DT | sized(DT) | { void ?{}( DT &, DT ); void ^?{}( DT & ); DT & ?+=?( DT &, one_t ); } )
     34        DT & ?++( DT & x ) { DT tmp = x; x += 1; return tmp; }
    3335
    34 static inline forall( dtype T | { T & ?-=?( T &, one_t ); } )
    35 T & --? ( T & x ) { return x -= 1; }
     36        forall( dtype DT | { DT & ?-=?( DT &, one_t ); } )
     37        DT & --?( DT & x ) { return x -= 1; }
    3638
    37 static inline forall( dtype T | sized(T) | { void ?{}( T &, T ); void ^?{}( T & ); T & ?-=?( T &, one_t ); } )
    38 T & ?-- ( T & x ) { T tmp = x; x -= 1; return tmp; }
     39        forall( dtype DT | sized(DT) | { void ?{}( DT &, DT ); void ^?{}( DT & ); DT & ?-=?( DT &, one_t ); } )
     40        DT & ?--( DT & x ) { DT tmp = x; x -= 1; return tmp; }
     41} // distribution
    3942
    4043// universal typed pointer constant
    41 
    42 static inline forall( dtype T ) T * intptr( uintptr_t addr ) { return (T *)addr; }
     44// Compiler issue: there is a problem with anonymous types that do not have a size.
     45static inline forall( dtype DT | sized(DT) ) DT * intptr( uintptr_t addr ) { return (DT *)addr; }
    4346
    4447// exponentiation operator implementation
     
    5356} // extern "C"
    5457
    55 static inline float ?\?( float x, float y ) { return powf( x, y ); }
    56 static inline double ?\?( double x, double y ) { return pow( x, y ); }
    57 static inline long double ?\?( long double x, long double y ) { return powl( x, y ); }
    58 static inline float _Complex ?\?( float _Complex x, _Complex float y ) { return cpowf(x, y ); }
    59 static inline double _Complex ?\?( double _Complex x, _Complex double y ) { return cpow( x, y ); }
    60 static inline long double _Complex ?\?( long double _Complex x, _Complex long double y ) { return cpowl( x, y ); }
     58static inline {
     59        float ?\?( float x, float y ) { return powf( x, y ); }
     60        double ?\?( double x, double y ) { return pow( x, y ); }
     61        long double ?\?( long double x, long double y ) { return powl( x, y ); }
     62        float _Complex ?\?( float _Complex x, _Complex float y ) { return cpowf(x, y ); }
     63        double _Complex ?\?( double _Complex x, _Complex double y ) { return cpow( x, y ); }
     64        long double _Complex ?\?( long double _Complex x, _Complex long double y ) { return cpowl( x, y ); }
     65} // distribution
    6166
    62 static inline long int ?\?( long int ep, unsigned long int y ) { // disallow negative exponent
    63         if ( y == 0 ) return 1;                                                         // base case
    64         if ( ep == 2 ) return ep << (y - 1);                            // special case, positive shifting only
    65         typeof( ep ) op = 1;                                                            // accumulate odd product
    66         for ( ; y > 1; y >>= 1 ) {                                                      // squaring exponentiation, O(log2 y)
    67                 if ( (y & 1) == 1 ) op *= ep;                                   // odd ?
    68                 ep *= ep;
    69         } // for
    70         return ep * op;
    71 } // ?\?
     67#define __CFA_BASE_COMP_1__() if ( ep == 1 ) return 1
     68#define __CFA_BASE_COMP_2__() if ( ep == 2 ) return ep << (y - 1)
     69#define __CFA_EXP_OVERFLOW__() if ( y >= sizeof(y) * CHAR_BIT ) return 0
    7270
    73 static inline forall( otype T | { void ?{}( T & this, one_t ); T ?*?( T, T ); } )
    74 T ?\?( T ep, unsigned long int y ) {
    75         if ( y == 0 ) return 1;
    76         T op = 1;
    77         for ( ; y > 1; y >>= 1 ) {                                                      // squaring exponentiation, O(log2 y)
    78                 if ( (y & 1) == 1 ) op = op * ep;                               // odd ?
    79                 ep = ep * ep;
    80         } // for
    81         return ep * op;
    82 } // ?\?
     71#define __CFA_EXP__() \
     72        if ( y == 0 ) return 1;                                                         /* convention */ \
     73        __CFA_BASE_COMP_1__();                                                          /* base case */ \
     74        __CFA_BASE_COMP_2__();                                                          /* special case, positive shifting for integral types */ \
     75        __CFA_EXP_OVERFLOW__();                                                         /* immediate overflow, negative exponent > 2^size-1 */ \
     76        typeof(ep) op = 1;                                                                      /* accumulate odd product */ \
     77        for ( ; y > 1; y >>= 1 ) {                                                      /* squaring exponentiation, O(log2 y) */ \
     78                if ( (y & 1) == 1 ) op = op * ep;                               /* odd ? */ \
     79                ep = ep * ep; \
     80        } \
     81        return ep * op
    8382
    84 // unsigned computation may be faster and larger
    85 static inline unsigned long int ?\?( unsigned long int ep, unsigned long int y ) { // disallow negative exponent
    86         if ( y == 0 ) return 1;                                                         // base case
    87         if ( ep == 2 ) return ep << (y - 1);                            // special case, positive shifting only
    88         typeof( ep ) op = 1;                                                            // accumulate odd product
    89         for ( ; y > 1; y >>= 1 ) {                                                      // squaring exponentiation, O(log2 y)
    90                 if ( (y & 1) == 1 ) op *= ep;                                   // odd ?
    91                 ep *= ep;
    92         } // for
    93         return ep * op;
    94 } // ?\?
     83static inline {
     84        long int ?\?( int ep, unsigned int y ) { __CFA_EXP__(); }
     85        long int ?\?( long int ep, unsigned long int y ) { __CFA_EXP__(); }
     86        // unsigned computation may be faster and larger
     87        unsigned long int ?\?( unsigned int ep, unsigned int y ) { __CFA_EXP__(); }
     88        unsigned long int ?\?( unsigned long int ep, unsigned long int y ) { __CFA_EXP__(); }
     89} // distribution
    9590
    96 static inline double ?\?( long int x, signed long int y ) {     // allow negative exponent
    97         if ( y >=  0 ) return (double)(x \ (unsigned long int)y);
    98         else return 1.0 / x \ (unsigned int)(-y);
    99 } // ?\?
     91#undef __CFA_BASE_COMP_1__
     92#undef __CFA_BASE_COMP_2__
     93#undef __CFA_EXP_OVERFLOW__
     94#define __CFA_BASE_COMP_1__()
     95#define __CFA_BASE_COMP_2__()
     96#define __CFA_EXP_OVERFLOW__()
    10097
    101 // FIXME (x \ (unsigned long int)y) relies on X ?\?(T, unsigned long) a function that is neither
    102 // defined, nor passed as an assertion parameter. Without user-defined conversions, cannot specify
    103 // X as a type that casts to double, yet it doesn't make sense to write functions with that type
    104 // signature where X is double.
     98static inline forall( otype OT | { void ?{}( OT & this, one_t ); OT ?*?( OT, OT ); } ) {
     99        OT ?\?( OT ep, unsigned int y ) { __CFA_EXP__(); }
     100        OT ?\?( OT ep, unsigned long int y ) { __CFA_EXP__(); }
     101} // distribution
    105102
    106 // static inline forall( otype T | { void ?{}( T & this, one_t ); T ?*?( T, T ); double ?/?( double, T ); } )
    107 // double ?\?( T x, signed long int y ) {
    108 //     if ( y >=  0 ) return (double)(x \ (unsigned long int)y);
    109 //     else return 1.0 / x \ (unsigned long int)(-y);
    110 // } // ?\?
     103#undef __CFA_BASE_COMP_1__
     104#undef __CFA_BASE_COMP_2__
     105#undef __CFA_EXP_OVERFLOW__
    111106
    112 static inline long int ?\=?( long int & x, unsigned long int y ) { x = x \ y; return x; }
    113 static inline unsigned long int ?\=?( unsigned long int & x, unsigned long int y ) { x = x \ y; return x; }
    114 static inline int ?\=?( int & x, unsigned long int y ) { x = x \ y; return x; }
    115 static inline unsigned int ?\=?( unsigned int & x, unsigned long int y ) { x = x \ y; return x; }
     107static inline {
     108        long int ?\=?( long int & x, unsigned long int y ) { x = x \ y; return x; }
     109        unsigned long int ?\=?( unsigned long int & x, unsigned long int y ) { x = x \ y; return x; }
     110        int ?\=?( int & x, unsigned long int y ) { x = x \ y; return x; }
     111        unsigned int ?\=?( unsigned int & x, unsigned long int y ) { x = x \ y; return x; }
     112} // distribution
    116113
    117114// Local Variables: //
  • libcfa/src/rational.cfa

    r2b10f95 r86fb8f2  
    1010// Created On       : Wed Apr  6 17:54:28 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Dec 23 22:56:49 2018
    13 // Update Count     : 170
     12// Last Modified On : Wed Mar 27 08:45:59 2019
     13// Update Count     : 180
    1414//
    1515
     
    5454        void ?{}( Rational(RationalImpl) & r, RationalImpl n, RationalImpl d ) {
    5555                RationalImpl t = simplify( n, d );                              // simplify
    56                 r.numerator = n / t;
    57                 r.denominator = d / t;
     56                r.[numerator, denominator] = [n / t, d / t];
    5857        } // rational
    5958
     
    7877                RationalImpl prev = r.numerator;
    7978                RationalImpl t = gcd( abs( n ), r.denominator ); // simplify
    80                 r.numerator = n / t;
    81                 r.denominator = r.denominator / t;
     79                r.[numerator, denominator] = [n / t, r.denominator / t];
    8280                return prev;
    8381        } // numerator
     
    8684                RationalImpl prev = r.denominator;
    8785                RationalImpl t = simplify( r.numerator, d );    // simplify
    88                 r.numerator = r.numerator / t;
    89                 r.denominator = d / t;
     86                r.[numerator, denominator] = [r.numerator / t, d / t];
    9087                return prev;
    9188        } // denominator
     
    120117
    121118        Rational(RationalImpl) +?( Rational(RationalImpl) r ) {
    122                 Rational(RationalImpl) t = { r.numerator, r.denominator };
    123                 return t;
     119                return (Rational(RationalImpl)){ r.numerator, r.denominator };
    124120        } // +?
    125121
    126122        Rational(RationalImpl) -?( Rational(RationalImpl) r ) {
    127                 Rational(RationalImpl) t = { -r.numerator, r.denominator };
    128                 return t;
     123                return (Rational(RationalImpl)){ -r.numerator, r.denominator };
    129124        } // -?
    130125
    131126        Rational(RationalImpl) ?+?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    132127                if ( l.denominator == r.denominator ) {                 // special case
    133                         Rational(RationalImpl) t = { l.numerator + r.numerator, l.denominator };
    134                         return t;
     128                        return (Rational(RationalImpl)){ l.numerator + r.numerator, l.denominator };
    135129                } else {
    136                         Rational(RationalImpl) t = { l.numerator * r.denominator + l.denominator * r.numerator, l.denominator * r.denominator };
    137                         return t;
     130                        return (Rational(RationalImpl)){ l.numerator * r.denominator + l.denominator * r.numerator, l.denominator * r.denominator };
    138131                } // if
    139132        } // ?+?
     
    141134        Rational(RationalImpl) ?-?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    142135                if ( l.denominator == r.denominator ) {                 // special case
    143                         Rational(RationalImpl) t = { l.numerator - r.numerator, l.denominator };
    144                         return t;
     136                        return (Rational(RationalImpl)){ l.numerator - r.numerator, l.denominator };
    145137                } else {
    146                         Rational(RationalImpl) t = { l.numerator * r.denominator - l.denominator * r.numerator, l.denominator * r.denominator };
    147                         return t;
     138                        return (Rational(RationalImpl)){ l.numerator * r.denominator - l.denominator * r.numerator, l.denominator * r.denominator };
    148139                } // if
    149140        } // ?-?
    150141
    151142        Rational(RationalImpl) ?*?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    152                 Rational(RationalImpl) t = { l.numerator * r.numerator, l.denominator * r.denominator };
    153                 return t;
     143                return (Rational(RationalImpl)){ l.numerator * r.numerator, l.denominator * r.denominator };
    154144        } // ?*?
    155145
    156146        Rational(RationalImpl) ?/?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    157147                if ( r.numerator < (RationalImpl){0} ) {
    158                         r.numerator = -r.numerator;
    159                         r.denominator = -r.denominator;
     148                        r.[numerator, denominator] = [-r.numerator, -r.denominator];
    160149                } // if
    161                 Rational(RationalImpl) t = { l.numerator * r.denominator, l.denominator * r.numerator };
    162                 return t;
     150                return (Rational(RationalImpl)){ l.numerator * r.denominator, l.denominator * r.numerator };
    163151        } // ?/?
    164152
     
    167155        forall( dtype istype | istream( istype ) | { istype & ?|?( istype &, RationalImpl & ); } )
    168156        istype & ?|?( istype & is, Rational(RationalImpl) & r ) {
    169                 RationalImpl t;
    170157                is | r.numerator | r.denominator;
    171                 t = simplify( r.numerator, r.denominator );
     158                RationalImpl t = simplify( r.numerator, r.denominator );
    172159                r.numerator /= t;
    173160                r.denominator /= t;
     
    185172        } // distribution
    186173} // distribution
     174
     175forall( otype RationalImpl | arithmetic( RationalImpl ) | { RationalImpl ?\?( RationalImpl, unsigned long ); } )
     176Rational(RationalImpl) ?\?( Rational(RationalImpl) x, long int y ) {
     177        if ( y < 0 ) {
     178                return (Rational(RationalImpl)){ x.denominator \ -y, x.numerator \ -y };
     179        } else {
     180                return (Rational(RationalImpl)){ x.numerator \ y, x.denominator \ y };
     181        } // if
     182}
    187183
    188184// conversion
  • libcfa/src/rational.hfa

    r2b10f95 r86fb8f2  
    1212// Created On       : Wed Apr  6 17:56:25 2016
    1313// Last Modified By : Peter A. Buhr
    14 // Last Modified On : Tue Dec  4 23:07:46 2018
    15 // Update Count     : 106
     14// Last Modified On : Tue Mar 26 23:16:10 2019
     15// Update Count     : 109
    1616//
    1717
     
    9898} // distribution
    9999
     100forall( otype RationalImpl | arithmetic( RationalImpl ) |{RationalImpl ?\?( RationalImpl, unsigned long );} )
     101Rational(RationalImpl) ?\?( Rational(RationalImpl) x, long int y );
     102
    100103// conversion
    101104forall( otype RationalImpl | arithmetic( RationalImpl ) | { double convert( RationalImpl ); } )
  • tests/.expect/KRfunctions.x64.txt

    r2b10f95 r86fb8f2  
    8282    signed int _X1ai_2;
    8383    signed int _X1bi_2;
    84     signed int *(*_tmp_cp_ret2)(signed int _X1xi_1, signed int _X1yi_1);
    85     ((void)(_X1xFPi_ii__2=(((void)(_tmp_cp_ret2=_X3f10FFPi_ii__iPiPid__1(3, (&_X1ai_2), (&_X1bi_2), 3.5))) , _tmp_cp_ret2)));
    86     ((void)(_tmp_cp_ret2) /* ^?{} */);
     84    signed int *(*_tmp_cp_ret4)(signed int _X1xi_1, signed int _X1yi_1);
     85    ((void)(_X1xFPi_ii__2=(((void)(_tmp_cp_ret4=_X3f10FFPi_ii__iPiPid__1(3, (&_X1ai_2), (&_X1bi_2), 3.5))) , _tmp_cp_ret4)));
     86    ((void)(_tmp_cp_ret4) /* ^?{} */);
    8787    const signed int _X2f1Fi_iPiPi__2(signed int _X1ai_2, signed int *_X1bPi_2, signed int *_X1cPi_2){
    8888        __attribute__ ((unused)) const signed int _X10_retval_f1Ki_2;
  • tests/.expect/completeTypeError.txt

    r2b10f95 r86fb8f2  
    8787   void
    8888 )
    89  Environment:( _74_0_T ) -> instance of type T (not function type) (no widening)
     89 Environment:( _99_0_T ) -> instance of type T (not function type) (no widening)
    9090
    9191
  • tests/.expect/declarationSpecifier.x64.txt

    r2b10f95 r86fb8f2  
    698698signed int main(signed int _X4argci_1, char **_X4argvPPc_1, char **_X4envpPPc_1){
    699699    __attribute__ ((unused)) signed int _X12_retval_maini_1;
    700     signed int _tmp_cp_ret2;
    701     ((void)(_X12_retval_maini_1=(((void)(_tmp_cp_ret2=invoke_main(_X4argci_1, _X4argvPPc_1, _X4envpPPc_1))) , _tmp_cp_ret2)) /* ?{} */);
    702     ((void)(_tmp_cp_ret2) /* ^?{} */);
     700    signed int _tmp_cp_ret4;
     701    ((void)(_X12_retval_maini_1=(((void)(_tmp_cp_ret4=invoke_main(_X4argci_1, _X4argvPPc_1, _X4envpPPc_1))) , _tmp_cp_ret4)) /* ?{} */);
     702    ((void)(_tmp_cp_ret4) /* ^?{} */);
    703703    return _X12_retval_maini_1;
    704704}
  • tests/.expect/extension.x64.txt

    r2b10f95 r86fb8f2  
    186186    __extension__ signed int _X1ci_2;
    187187    ((void)(__extension__ _X1ai_2=(__extension__ _X1bi_2+__extension__ _X1ci_2)));
    188     signed int _tmp_cp_ret2;
    189     ((void)(((void)(_tmp_cp_ret2=__extension__ _X4fredFi_i__1(3))) , _tmp_cp_ret2));
    190     ((void)(_tmp_cp_ret2) /* ^?{} */);
     188    signed int _tmp_cp_ret4;
     189    ((void)(((void)(_tmp_cp_ret4=__extension__ _X4fredFi_i__1(3))) , _tmp_cp_ret4));
     190    ((void)(_tmp_cp_ret4) /* ^?{} */);
    191191    __extension__ signed int _X4maryFi_i__2(signed int _X1pi_2){
    192192        __attribute__ ((unused)) signed int _X12_retval_maryi_2;
  • tests/.expect/gccExtensions.x64.txt

    r2b10f95 r86fb8f2  
    171171signed int main(signed int _X4argci_1, char **_X4argvPPc_1, char **_X4envpPPc_1){
    172172    __attribute__ ((unused)) signed int _X12_retval_maini_1;
    173     signed int _tmp_cp_ret2;
    174     ((void)(_X12_retval_maini_1=(((void)(_tmp_cp_ret2=invoke_main(_X4argci_1, _X4argvPPc_1, _X4envpPPc_1))) , _tmp_cp_ret2)) /* ?{} */);
    175     ((void)(_tmp_cp_ret2) /* ^?{} */);
     173    signed int _tmp_cp_ret4;
     174    ((void)(_X12_retval_maini_1=(((void)(_tmp_cp_ret4=invoke_main(_X4argci_1, _X4argvPPc_1, _X4envpPPc_1))) , _tmp_cp_ret4)) /* ?{} */);
     175    ((void)(_tmp_cp_ret4) /* ^?{} */);
    176176    return _X12_retval_maini_1;
    177177}
  • tests/.expect/math1.txt

    r2b10f95 r86fb8f2  
    1010expm1:1.71828 1.71828182845905 1.71828182845904524
    1111pow:1 1 1 0.273957+0.583701i 0.273957253830121+0.583700758758615i -0.638110484918098871+0.705394566961838155i
    12 \ 16 256
    13 \ 912673 256 64 -64 0.015625 -0.015625 18.3791736799526 0.264715-1.1922i
     1216 \ 2 = 256
     13912673 256 64 -64 0 0
     140.015625 -0.015625 18.3791736799526 0.264715-1.1922i
     150 0 18.3791736799526 0.264715-1.1922i
     1616
     174 16
  • tests/coroutine/pingpong.cfa

    r2b10f95 r86fb8f2  
    1010// Created On       : Wed Sep 20 11:55:23 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Mar 22 13:37:52 2019
    13 // Update Count     : 30
     12// Last Modified On : Tue Mar 26 17:54:14 2019
     13// Update Count     : 35
    1414//
    1515
     
    2020        const char * name;
    2121        /* const */ unsigned int N;
    22         PingPong * part;
     22        PingPong & part;
    2323};
    2424
    2525void ?{}( PingPong & this, const char * name, unsigned int N, PingPong & part ) {
    26         (this.__cor){name};
    27         this.name = name;
    28         this.N = N;
    29         this.part = &part;
     26        this.[name, N] = [name, N];  &this.part = &part;
    3027}
    3128void ?{}( PingPong & this, const char * name, unsigned int N ) {
    32         this{ name, N, *(PingPong *)0 };
     29        this{ name, N, *0p };                                                           // call first constructor
    3330}
    3431void cycle( PingPong & pingpong ) {
     
    3633}
    3734void partner( PingPong & this, PingPong & part ) {
    38         this.part = &part;
     35        &this.part = &part;
    3936        resume( this );
    4037}
    41 void main( PingPong & pingpong ) {                                              // ping's starter ::main, pong's starter ping
    42         for ( pingpong.N ) {                                                            // N ping-pongs
    43                 sout | pingpong.name;
    44                 cycle( *pingpong.part );
     38void main( PingPong & pingpong ) with(pingpong) {               // ping's starter ::main, pong's starter ping
     39        for ( N ) {                                                                                     // N ping-pongs
     40                sout | name;
     41                cycle( part );
    4542        } // for
    4643}
  • tests/math1.cfa

    r2b10f95 r86fb8f2  
    1010// Created On       : Fri Apr 22 14:59:21 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Dec 12 16:28:49 2018
    13 // Update Count     : 89
     12// Last Modified On : Mon Mar 25 22:56:47 2019
     13// Update Count     : 109
    1414//
    1515
     
    4949        unsigned int e = 2;
    5050    b \= e;
    51     sout | "\\" | b | b \ e;
    52     sout | "\\" | 'a' \ 3u | 2 \ 8u | 4 \ 3u | -4 \ 3u | nonl;
     51    sout | b | "\\" | e | "= " | b \ e;
     52    sout | 'a' \ 3 | 2 \ 8 | 4 \ 3 | -4 \ 3 | 4 \ -3 | -4 \ -3;
     53        sout | 4.0 \ -3 | -4.0 \ -3 | 4.0 \ 2.1 | (1.0f+2.0fi) \ (3.0f+2.0fi);
    5354        sout | 4 \ -3 | -4 \ -3 | 4.0 \ 2.1 | (1.0f+2.0fi) \ (3.0f+2.0fi);
     55
     56        struct S { int i; };
     57        double ?*?( double d, S s ) { return d * s.i; }
     58        double ?/?( double d, S s ) { return d / s.i; }
     59        S ?\?( S s, unsigned long y ) { return (S){ s.i \ y }; }
     60        ofstream & ?|?( ofstream & os, S s ) { return os | s.i; }
     61        void ?|?( ofstream & os, S s ) { (ofstream &)(os | s); nl( os ); }
     62        S s = { 4 };
     63        S x = s \ 2;
     64        sout | x;
     65        sout | s.i | s \ 2u;
    5466} // main
    5567
  • tests/rational.cfa

    r2b10f95 r86fb8f2  
    1010// Created On       : Mon Mar 28 08:43:12 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Mar 19 08:30:28 2019
    13 // Update Count     : 73
     12// Last Modified On : Wed Mar 27 07:37:17 2019
     13// Update Count     : 80
    1414//
    1515
     
    5454        sout | a * b;
    5555        sout | a / b;
     56//      sout | a \ 2 | b \ 2; // FIX ME
     57//      sout | a \ -2 | b \ -2;
    5658
    5759        sout | "conversion";
Note: See TracChangeset for help on using the changeset viewer.