Changes in / [68ea8d2:97f9619]


Ignore:
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • Makefile.am

    r68ea8d2 r97f9619  
    1111## Created On       : Sun May 31 22:14:18 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Wed May 17 11:02:34 2023
    14 ## Update Count     : 56
     13## Last Modified On : Tue Jul 16 16:59:12 2024
     14## Update Count     : 57
    1515###############################################################################
    1616
     
    3535man1_MANS = doc/man/cfa.1
    3636
    37 EXTRA_DIST = LICENSE doc/man/cfa.1 libcfa/configure libcfa/Makefile.dist.am libcfa/Makefile.dist.in tools/build/distcc_hash tools/build/push2dist.sh
     37EXTRA_DIST = LICENSE doc/man/cfa.1 libcfa/configure libcfa/Makefile.dist.am libcfa/Makefile.dist.in tools/build/distcc_hash tools/build/push2dist.sh tools/prettyprinter
    3838
    3939debug ?= yes
  • doc/bibliography/pl.bib

    r68ea8d2 r97f9619  
    18631863    key         = {concurrent locking},
    18641864    author      = {Peter A. Buhr and David Dice and Wim H. Hesselink},
    1865     title       = {concurrent-locking},
     1865    title       = {Concurrent locking algorithms},
    18661866    howpublished= {\url{https://github.com/pabuhr/concurrent-locking}},
    18671867}
     
    40014001    organization= {Google},
    40024002    year        = 2009,
    4003     note        = {\url{http://golang.org/ref/spec}},
     4003    note        = {\url{https://go.dev/ref/spec}},
    40044004}
    40054005
     
    41804180    number      = 12,
    41814181    pages       = {2463-2500},
    4182     note        = {\url{https://onlinelibrary.wiley.com/doi/10.1002/spe.3262}},
    41834182}
    41844183
     
    78027801@book{Scott24,
    78037802    author      = {Michael L. Scott and Trevor Brown},
    7804     booktitle   = {Shared-Memory Synchronization},
     7803    title       = {Shared-Memory Synchronization},
    78057804    series      = {Synthesis Lectures on Computer Architecture},
    78067805    edition     = {2nd},
     
    85328531    key         = {TIOBE Index},
    85338532    author      = {{TIOBE Index}},
    8534     howpublished= {\url{http://www.tiobe.com/tiobe_index}},
     8533    howpublished= {\url{https://www.tiobe.com/tiobe-index}},
    85358534}
    85368535
  • doc/user/Makefile

    r68ea8d2 r97f9619  
    66TeXLIB = .:${Macros}:${Build}:
    77LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error -output-directory=${Build}
    8 BibTeX = BIBINPUTS=../bibliography: && export BIBINPUTS && bibtex
     8BibDir = ../bibliography
     9BibTeX = BIBINPUTS=${BibDir}: && export BIBINPUTS && bibtex
    910
    1011MAKEFLAGS = --no-print-directory --silent #
     
    6162
    6263${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} ${Macros}/common.tex ${Macros}/common.sty \
    63                 ${Macros}/lstlang.sty ${Macros}/indexstyle ../bibliography/pl.bib build/version | ${Build}
     64                ${Macros}/lstlang.sty ${Macros}/indexstyle ${BibDir}/pl.bib build/version | ${Build}
    6465        # Conditionally create an empty *.ind (index) file for inclusion until makeindex is run.
    6566        if [ ! -r ${basename $@}.ind ] ; then touch ${Build}/${basename $@}.ind ; fi
  • libcfa/src/enum.cfa

    r68ea8d2 r97f9619  
    4242        if ( eof( is ) ) throwResume ExceptionInst( missing_data );
    4343
    44         // Match input enumerator string to enumerator labels.
     44        // Match longest input enumerator string to enumerator labels, where enumerator names are unique.
     45
    4546        int N = Countof( e ), lnths[N], max = 0;
    4647//      printf( "N %d\n", N );
     
    6061        for ( c; max ) {
    6162                int args = fmt( is, "%c", &ch );                                // read character
    62                 if ( eof( is ) ) {
     63          if ( eof( is ) ) {
    6364//                      fprintf( stderr, "Eof1\n" );
    6465                        if ( c == 0 ) return is;                                        // no characters read ?
    65                         clear( is );                                                            // => reset EOF => detect again on next read
     66                        clear( is );                                                            // => read something => reset EOF => detect again on next read
    6667//                      fprintf( stderr, "Eof2\n" );
    67                         goto W;
    68                 }
     68                        break;
     69                } // if
    6970                if ( args != 1 ) throwResume ExceptionInst( missing_data );
     71
    7072//              printf( "read '%c'\n", ch );
    71                 for ( i; N ) {
     73                for ( i; N ) {                                                                  // scan enumeration strings for winner
    7274//                      printf( "%d %d %d\n", c, i, lnths[i] );
    7375                        if ( c < lnths[i] ) {                                           // eligible for this checking round ?
    7476                                char match = label( fromInt( i ) )[c];  // optimization
    7577//                              printf( "%c '%c'\n", match, ch );
     78                                // Stop on first match, could be other matches.
    7679                                if ( (match == ch) && (c == 0 || curr == label( fromInt( i ) )[c - 1]) ) {
    7780//                                      printf( "match %d %d %d '%c' '%c' '%c' '%c' 'c'\n", c, i, lnths[i], match, ch, prev, label( fromInt( i ) )[c - 1] );
     
    9295//              fprintf( stderr, "finished2 %d\n", win );
    9396        } // for
    94   W :;
    95         for ( i; N ) {                                                                          // scan for winner, must succeed
     97  W: ;
     98        for ( i; N ) {                                                                          // scan enumeration strings for winner
    9699                if ( win == lnths[i] - 1 ) {
    97100                        char match = label( fromInt( i ) )[win];        // optimization
     
    100103                                e = fromInt( i );
    101104                                break;
    102                         }
     105                        } // if
    103106                } // if
    104107        } else {
  • libcfa/src/iostream.cfa

    r68ea8d2 r97f9619  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul 12 05:45:45 2024
    13 // Update Count     : 2019
     12// Last Modified On : Mon Jul 15 08:16:48 2024
     13// Update Count     : 2020
    1414//
    1515
     
    781781                // Optional leading whitespace at start of strings.
    782782                fmt( is, " " FALSE "%n", &len );                                // try false
    783                 if ( len != sizeof( FALSE ) - 1 ) {                             // remove null terminate
     783                if ( len != sizeof( FALSE ) - 1 ) {                             // -1 removes null terminate
    784784                        fmt( is, " " TRUE "%n", &len );                         // try true
    785785                        if ( len != sizeof( TRUE ) - 1 ) throwResume ExceptionInst( missing_data );
  • src/AST/Print.cpp

    r68ea8d2 r97f9619  
    566566                ++indent;
    567567                safe_print( node->cond );
    568                 os << indent-1 << "... with body:" << endl;
    569                 safe_print( node->body );
    570568
    571569                if ( ! node->inits.empty() ) {
     
    573571                        printAll( node->inits );
    574572                }
     573
     574                os << indent-1 << "... with body:" << endl;
     575                safe_print( node->body );
     576
     577                if ( node->else_ ) {
     578                        os << indent-1 << "... with else:" << endl;
     579                        os << indent;
     580                        node->else_->accept( *this );
     581                }
     582
    575583                --indent;
    576584
     
    614622                        --indent;
    615623                }
     624
     625                if ( node->else_ ) {
     626                        os << indent << "... with else:" << endl;
     627                        ++indent;
     628                        os << indent;
     629                        node->else_->accept( *this );
     630                        --indent;
     631                }
     632
    616633                os << endl;
    617634                print( node->labels );
  • src/CodeGen/CodeGenerator.cpp

    r68ea8d2 r97f9619  
    11951195        stmt->body->accept( *visitor );
    11961196
    1197         output << indent;
    1198 
    11991197        if ( stmt->isDoWhile ) {
    12001198                output << " while (";
    12011199                stmt->cond->accept( *visitor );
    1202                 output << ");";
     1200                output << ( ( nullptr == stmt->else_ ) ? ");" : ")" );
     1201        }
     1202        if ( stmt->else_ ) {
     1203                output << " else ";
     1204                stmt->else_->accept( *visitor );
    12031205        }
    12041206}
     
    12251227                stmt->body->accept( *visitor );
    12261228        }
     1229
     1230        if ( nullptr != stmt->else_ ) {
     1231                assertf( !options.genC, "Loop else should not reach code generation." );
     1232                output << " else ";
     1233                stmt->else_->accept( *visitor );
     1234        }
    12271235}
    12281236
  • src/ControlStruct/MultiLevelExit.cpp

    r68ea8d2 r97f9619  
    7878                stmt( stmt ), firstTarget( breakExit ), secondTarget(), kind( TryStmtK ) {}
    7979
     80        // Check if this entry can be the target of the given type of control flow.
    8081        bool isContTarget() const { return kind <= WhileDoStmtK; }
    8182        bool isBreakTarget() const { return kind != CaseClauseK; }
     
    207208
    208209        // If the label is empty, do not add unused attribute.
    209   if ( originalTarget.empty() ) return size;
     210        if ( originalTarget.empty() ) return size;
    210211
    211212        // Search for a label that matches the originalTarget.
     
    343344                assert(0);
    344345        }
     346        assert( !exitLabel.empty() );
    345347
    346348        // Add unused attribute to silence warnings.
     
    486488                }
    487489
    488                 auto caseStmt = mutStmt->cases.back().get();
    489                 auto mutCase = mutate( caseStmt );
    490                 mutStmt->cases.back() = mutCase;
     490                auto mutCase = mutStmt->cases.back().get_and_mutate();
    491491
    492492                Label label( mutCase->location, "breakLabel" );
     
    597597template<typename LoopNode>
    598598void MultiLevelExitCore::prehandleLoopStmt( const LoopNode * loopStmt ) {
    599         // Remember is loop before going onto mutate the body.
     599        // Create temporary labels and mark the enclosing loop before traversal.
    600600        // The labels will be folded in if they are used.
    601601        Label breakLabel = newLabel( "loopBreak", loopStmt );
    602602        Label contLabel = newLabel( "loopContinue", loopStmt );
    603603        enclosing_control_structures.emplace_back( loopStmt, breakLabel, contLabel );
    604         // labels are added temporarily to see if they are used and then added permanently in postvisit if ther are used
    605         // children will tag labels as being used during their traversal which occurs before postvisit
    606 
    607         // GuardAction calls the lambda after the node is done being visited
     604
    608605        GuardAction( [this](){ enclosing_control_structures.pop_back(); } );
     606
     607        // Because of fixBlock, this should be empty now (and must be).
     608        assert( nullptr == loopStmt->else_ );
    609609}
    610610
     
    617617        // Now check if the labels are used and add them if so.
    618618        return mutate_field( loopStmt, &LoopNode::body, mutateLoop( loopStmt->body, entry ) );
    619         // this call to mutate_field compares loopStmt->body and the result of mutateLoop
    620         //              if they are the same the node isn't mutated, if they differ then the new mutated node is returned
    621         //              the stmts will only differ if a label is used
    622619}
    623620
     
    639636
    640637                ptr<Stmt> else_stmt = nullptr;
    641                 const Stmt * loop_kid = nullptr;
     638                const Stmt * to_visit;
    642639                // check if loop node and if so add else clause if it exists
    643                 const WhileDoStmt * whilePtr = kid.as<WhileDoStmt>();
    644                 if ( whilePtr && whilePtr->else_ ) {
    645                         else_stmt = whilePtr->else_;
    646                         loop_kid = mutate_field( whilePtr, &WhileDoStmt::else_, nullptr );
    647                 }
    648                 const ForStmt * forPtr = kid.as<ForStmt>();
    649                 if ( forPtr && forPtr->else_ ) {
    650                         else_stmt = forPtr->else_;
    651                         loop_kid = mutate_field( forPtr, &ForStmt::else_, nullptr );
    652                 }
    653 
     640                if ( auto ptr = kid.as<WhileDoStmt>() ; ptr && ptr->else_ ) {
     641                        else_stmt = ptr->else_;
     642                        to_visit = mutate_field( ptr, &WhileDoStmt::else_, nullptr );
     643                } else if ( auto ptr = kid.as<ForStmt>() ; ptr && ptr->else_ ) {
     644                        else_stmt = ptr->else_;
     645                        to_visit = mutate_field( ptr, &ForStmt::else_, nullptr );
     646                } else {
     647                        to_visit = kid.get();
     648                }
     649
     650                // This is the main (safe) visit of the child node.
    654651                try {
    655                         if (else_stmt) ret.push_back( loop_kid->accept( *visitor ) );
    656                         else ret.push_back( kid->accept( *visitor ) );
     652                        ret.push_back( to_visit->accept( *visitor ) );
    657653                } catch ( SemanticErrorException & e ) {
    658654                        errors.append( e );
    659655                }
    660656
    661                 if (else_stmt) ret.push_back(else_stmt);
    662 
    663                 if ( ! break_label.empty() ) {
     657                // The following sections handle visiting loop else clause and makes
     658                // sure breaking from a loop body does not execute that clause.
     659                Label local_break_label = std::move( break_label );
     660                break_label = Label( CodeLocation(), "" );
     661
     662                if ( else_stmt ) try {
     663                        ret.push_back( else_stmt->accept( *visitor ) );
     664                } catch ( SemanticErrorException & e ) {
     665                        errors.append( e );
     666                }
     667
     668                if ( !break_label.empty() ) {
    664669                        ret.push_back( labelledNullStmt( ret.back()->location, break_label ) );
    665670                        break_label = Label( CodeLocation(), "" );
    666671                }
    667         }
    668 
    669         if ( ! errors.isEmpty() ) {
     672
     673                // This handles a break from the body or non-loop statement.
     674                if ( !local_break_label.empty() ) {
     675                        ret.push_back( labelledNullStmt( ret.back()->location, local_break_label ) );
     676                }
     677        }
     678
     679        if ( !errors.isEmpty() ) {
    670680                throw errors;
    671681        }
  • tests/ctrl-flow/.expect/loop_else.txt

    r68ea8d2 r97f9619  
    6363(10 10)(9 9)(8 8)(7 7)(6 6)(5 5)(4 4)(3 3)(2 2)(1 1)(0 0)else
    6464
     65before begin else after
  • tests/ctrl-flow/loop_else.cfa

    r68ea8d2 r97f9619  
    7474                i -= 1.7;
    7575        } else { sout | "else"; }                                                                                                               sout | nl | nl;
    76        
     76
    7777        enum { N = 10 };
    7878        for ( N ) { sout | "N"; } else { sout | "else"; }                                                       sout | nl;
     
    109109        for ( s; (S){0} -~  (S){10,10} ~ (S){1} ) { sout | s; } else { sout | "else"; } sout | nl;
    110110        for ( s; (S){0} -~= (S){10,10} ) { sout | s; } else { sout | "else"; }           sout | nl;
    111         for ( s; (S){0} -~= (S){10,10} ~ (S){1} ) { sout | s; } else { sout | "else"; } sout | nl | nl;
     111        for ( s; (S){0} -~= (S){10,10} ~ (S){1} ) { sout | s; } else { sout | "else"; } sout | nl;
     112        sout | nl;
     113
     114        // A break (or a continue) in an else clause should target an outer loop.
     115        sout | "before";
     116        while ( true ) {
     117                sout | " begin";
     118                while ( false ) {
     119                        sout | "never";
     120                } else {
     121                        sout | " else";
     122                        break;
     123                }
     124                sout | " end";
     125        }
     126        sout | " after" | nl;
    112127}
Note: See TracChangeset for help on using the changeset viewer.