Changeset a724ac1


Ignore:
Timestamp:
Jun 12, 2017, 3:38:07 PM (4 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
1bc9dcb
Parents:
82ff584 (diff), 465ed18 (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:
1 added
15 edited

Legend:

Unmodified
Added
Removed
  • doc/working/exception/design.txt

    r82ff584 ra724ac1  
    11Design of Exceptions and EHM in Cforall:
    22
    3 Currently this is a combination of ideas and big questions that still have to
    4 be addressed. It also includes some other error handling options, how they
    5 interact and compare to exceptions.
     3
     4Exception Instances:
     5Currently, exceptions are integers (like errno).
     6
     7They are planned to be the new "tagged structures", which allows them to
     8exist in a simple hierarchy which shared functionality throughout. However
     9the tagged structures are not yet implemented so that will wait.
     10
     11A single built in exception is at the top of the hierarchy and all other
     12exceptions are its children. When you match against an exception, you match
     13for an exception and its children, so the top of the hierarchy is used as a
     14catch-all option.
     15
     16The shared functionality across exceptions has not been finalized, but will
     17probably include things like human readable descriptions and default handlers.
    618
    719
    8 What is an Exception:
     20Throwing:
     21There are currently two kinds of throws, "throw" for termination and
     22"throwResume" for resumption. Both keywords can be used to create a throw
     23statement. The kind of throw decides what handlers may catch the exception
     24and weither control flow can return to the throw site.
    925
    10 In other words what do we throw? What is matched against, how does it carry
    11 data with it? A very important question that has not been answered.
     26Syntax
     27"throw" exception ";"
     28"throwResume" exception ";"
    1229
    13 Option 1: Strutures
     30Non-local throws are allowed for resumption only. A target is an object with
     31a stack, with which it may propagate and handle the exception.
    1432
    15 Considering the current state of Cforall the most natural form of the
    16 exception would likely be a struture, implementing a trait repersenting the
    17 minimum features of an exception. This has many advantages, including arbitray
    18 fields, some polymorphism and it matches exceptations of many current systems.
     33Syntax
     34"throwResume" exception "_At" target ";"
    1935
    20 The main issue with this is matching, without OOP inheritance there is no
    21 exception hierarchy. Meaning all handling has to happen on the exact exception
    22 without the ease of grouping parents. There are several ways to attempt to
    23 recover this.
    24 
    25 The first is with conditional matching (a check after the type has been
    26 matched) which allows for matching particular values of a known type. However
    27 this does not dynamically expand and requires an extra step (as opposed to
    28 mearly allowing one). I would not recomend this as the primary method.
    29 
    30 Second is to try and use type casts/conversions to create an implicate
    31 hierachy, so that a catch clause catches anything of the given type or
    32 anything that converts to the given type.
    33 
    34 Plan9 (from what I know of it) would be a powerful tool here. Even with it,
    35 creating a hierarchy of types at runtime might be too expencive. Esecially
    36 since they are less likely to be tree like at that point.
    37 
    38 Option 2: Tags
    39 
    40 The other option is to introduce a new construct into the language. A tag
    41 repersents a type of exception, it is not a structure or variable (or even
    42 a normal type). It may be usable in some of those contexts.
    43 
    44 Tags can declare an existing tag as its parent. Tags can be caught by handlers
    45 that catch their parents. (There is a single base_exception that all other
    46 exceptions are children of eventually.) This allows for grouping of exceptions
    47 that repersent similar errors.
    48 
    49 Tags should also have some assotiated data, where and on what did the error
    50 occur. Keeping with the otherness of exception tags and allowing them to be
    51 expanded, using a parameter list. Each exception can have a list of paramters
    52 given to it on a throw. Each tag would have a declared list of parameters
    53 (which could be treated more like a set of fields as well). Child tags must
    54 use their parent's list as a prefix to their own, so that the parameters can
    55 be accessed when the child tag is matched against the parent.
    56 
    57 Option N: ...
    58 
    59 This list is not complete.
     36Termination throws unwind the stack until a handler is reached, control moves
     37onwards from the end of the handler. Resumption throws do not unwind, if a
     38handler is found and control will return to the throw after the exception is
     39handled.
    6040
    6141
    62 Seperating Termination and Resumption:
     42Catching:
     43The catch and handle of an exception is preformed with a try statement, which
     44also can have finally clauses to exceute on exit from the scope.
    6345
    64 Differentating the types of exceptions based on exception would be hard with
    65 exceptions as structures. It is possible with exceptions as tags by having
    66 two base exceptions, one for each type of throw. However recompining them
    67 to dual types would be harder.
     46Syntax
     47"try"
     48        try-block
     49( ("catch" | "catchResume")
     50  "(" exception_type [identifier] [";" conditional_expression] ")"
     51        catch-block
     52)*
     53("finally"
     54        finally-block
     55)?
    6856
    69 Reguardless, using different keywords would also be useful for clarity, even
    70 if it does not add functality. Using the C++ like keywords would be a good
    71 base. Resumption exceptions could use a different set (ex. raise->handle) or
    72 use resume as a qualifier on the existing statements.
     57Either at least 1 handler clause or the finally clasue must be given on each
     58try block. Each handler clause handles 1 of the two types of throws. Each
     59handler also specifies a type of exception it handles, and will handle all
     60children exceptions as well. In addition, a conditional expression which, if
     61included, must be true for the handler to catch the exception.
     62
     63The two types of handlers may be intermixed. Multiple handlers catching the
     64same type may also be used, to allow for fallbacks on false conditionals.
    7365
    7466
    75 Conditional Matching:
     67Implementation Overview:
    7668
    77 A possible useful feature, it allows for arbitrary checks on a catch block
    78 instead of merely matching a type. However there are few use cases that
    79 cannot be avoided with proper use of a type hierarchy, and this shrinks even
    80 further with a good use of re-throws.
     69The implementation has two main parts. The first is just a collection of the
     70support definitions we need, the data types and functions used within the
     71exception handling code. Second is a translation from Cforall code to C code
     72that uses those definitions to throw, catch and handle exceptions.
    8173
    82 Also it assumes one sweep, that might also be a problem. But might also give
    83 it an advantage over re-throws.
     74Termination handlers call a specially annotated function, passing it inner
     75functions that act as the varius sub-blocks. Termination throws use the
     76unwind library that checks the underlying code for those annotations. Each
     77time one is found some magic is used to check for a matching handler, if one
     78is found control goes to the special function which excecutes the handler and
     79returns.
     80
     81Resumption handlers maintain a linked list of stack allocated nodes that have
     82the handler functions attached. Throwing a resumption exception traverses this
     83list, and calls each handler, the handlers handle the exception if they can
     84and return if they did or not.
     85
     86Finally clauses just use stack cleanup to force a nested function, which has
     87the code from the finally clause, to execute when we leave that section.
    8488
    8589
    86 Alternatives: Implicate Handlers & Return Unions
     90Alternative Error Handling: Return Unions
    8791
    88 Both act as a kind of local version of an exception. Implicate handlers act as
    89 resumption exceptions and return unions like termination exceptions. By local
    90 I mean they work well at one or two levels of calls, but do not cover N levels
    91 as cleanly.
     92Return unions (Maybe and Result), are types that can encode a success or
     93other result in a single value. Maybe stores a value or nothing, Result stores
     94a value or an error.
    9295
    93 Implicate handles require a growing number of function pointers (which should
    94 not be used very often) to be passed to functions, creating and additional
    95 preformance cost. Return unions have to be checked and handled at every level,
    96 which has some preformance cost, but also can significantly clutter code.
    97 Proper tools can help with the latter.
     96For errors that are usually handled quite close to where they occur, these
     97can replace exceptions.
    9898
    99 However, they may work better at that local level as they do not require stack
    100 walking or unwinding. In addition they are closer to regular control flow and
    101 are easier to staticly check. So even if they can't replace exceptions
    102 (directly) they may still be worth using together.
    103 
    104 For instance, consider the Python iterator interface. It uses a single
    105 function, __next__, to access the next value and to signal the end of the
    106 sequence. If a value is returned, it is the next value, if the StopIteration
    107 exception is thrown the sequence has finished.
    108 
    109 However almost every use of an iterator will add a try-except block around the
    110 call site (possibly through for or next) to catch and handle the exception
    111 immediately, ignoring the advantages of more distant exception handling.
    112 
    113 In this case it may be cleaner to use a Maybe for both cases (as in Rust)
    114 which gives similar results without having to jump to the exception handler.
    115 This will likely handle the error case more efficiently and the success case a
    116 bit less so.
    117 
    118 It also mixes the error and regular control flow, which can hurt readablity,
    119 but very little if the handling is simple, for instance providing a default
    120 value. Similarly, if the error (or alternate outcome) is common enough
    121 encoding it in the function signature may be good commuication.
     99They tend to be faster and require similar or less amounts of code to handle.
     100However they can slow down the normal path with some extra conditionals and
     101can mix the normal and exceptional control flow path. If handling the error
     102is simple, and happens relatively frequently, this might be prefered but in
     103other cases it just hurts speed and readability.
    122104
    123105In short, these errors seem to be more effective when errors are likely and
     
    125107be handled locally, might be better off using these instead of exceptions.
    126108
    127 Also the implicate handlers and return unions could use exceptions as well.
    128 For instance, a useful default might handler might be to throw an exception,
    129 seaching up the stack for a solution if one is not locally provided.
    130 
    131 Or here is a possible helper for unpacking a Result value:
     109Also the return unions could use exceptions as well. Getting the improper
     110side of a return union might throw an exception. Or we can provide helpers
     111for results withe exceptions as in:
    132112                forall(otype T, otype E | exception(E))
    133113                T get_or_throw (Result(T, E) * this) {
    134                         if (is_success(this)) {
    135                                 return get_success(this);
     114                        if (has_value(this)) {
     115                                return get_value(this);
    136116                        } else {
    137                                 throw get_failure(this);
     117                                throw get_error(this);
    138118                        }
    139119                }
    140 So they can feed off of each other.
  • src/CodeGen/CodeGenerator.cc

    r82ff584 ra724ac1  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed May 10 14:45:00 2017
    13 // Update Count     : 484
     12// Last Modified On : Thu Jun  8 16:00:00 2017
     13// Update Count     : 485
    1414//
    1515
     
    908908        }
    909909
     910        void CodeGenerator::visit( ThrowStmt * throwStmt ) {
     911                assertf( ! genC, "Throw statements should not reach code generation." );
     912
     913                output << ((throwStmt->get_kind() == ThrowStmt::Terminate) ?
     914                           "throw" : "throwResume");
     915                if (throwStmt->get_expr()) {
     916                        output << " ";
     917                        throwStmt->get_expr()->accept( *this );
     918                }
     919                if (throwStmt->get_target()) {
     920                        output << " _At ";
     921                        throwStmt->get_target()->accept( *this );
     922                }
     923                output << ";";
     924        }
     925
    910926        void CodeGenerator::visit( WhileStmt * whileStmt ) {
    911927                if ( whileStmt->get_isDoWhile() ) {
  • src/CodeGen/CodeGenerator.h

    r82ff584 ra724ac1  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed May 10 10:57:00 2017
    13 // Update Count     : 51
     12// Last Modified On : Thu Jun  8 15:48:00 2017
     13// Update Count     : 52
    1414//
    1515
     
    9191                virtual void visit( BranchStmt * );
    9292                virtual void visit( ReturnStmt * );
     93                virtual void visit( ThrowStmt * );
    9394                virtual void visit( WhileStmt * );
    9495                virtual void visit( ForStmt * );
  • src/Parser/ParseNode.h

    r82ff584 ra724ac1  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Sat May 16 13:28:16 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Mar 17 15:42:18 2017
    13 // Update Count     : 777
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Jun 12 13:00:00 2017
     13// Update Count     : 779
    1414//
    1515
     
    393393Statement * build_return( ExpressionNode * ctl );
    394394Statement * build_throw( ExpressionNode * ctl );
     395Statement * build_resume( ExpressionNode * ctl );
     396Statement * build_resume_at( ExpressionNode * ctl , ExpressionNode * target );
    395397Statement * build_try( StatementNode * try_stmt, StatementNode * catch_stmt, StatementNode * finally_stmt );
    396 Statement * build_catch( DeclarationNode * decl, StatementNode * stmt, bool catchAny = false );
     398Statement * build_catch( CatchStmt::Kind kind, DeclarationNode *decl, ExpressionNode *cond, StatementNode *body );
    397399Statement * build_finally( StatementNode * stmt );
    398400Statement * build_compound( StatementNode * first );
  • src/Parser/StatementNode.cc

    r82ff584 ra724ac1  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Sat May 16 14:59:41 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  2 22:16:40 2017
    13 // Update Count     : 327
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Jun 12 13:03:00 2017
     13// Update Count     : 329
    1414//
    1515
     
    152152        return new ReturnStmt( noLabels, exps.size() > 0 ? exps.back() : nullptr );
    153153}
     154
    154155Statement *build_throw( ExpressionNode *ctl ) {
    155156        std::list< Expression * > exps;
    156157        buildMoveList( ctl, exps );
    157158        assertf( exps.size() < 2, "This means we are leaking memory");
    158         return new ReturnStmt( noLabels, !exps.empty() ? exps.back() : nullptr, true );
     159        return new ThrowStmt( noLabels, ThrowStmt::Terminate, !exps.empty() ? exps.back() : nullptr );
     160}
     161
     162Statement *build_resume( ExpressionNode *ctl ) {
     163        std::list< Expression * > exps;
     164        buildMoveList( ctl, exps );
     165        assertf( exps.size() < 2, "This means we are leaking memory");
     166        return new ThrowStmt( noLabels, ThrowStmt::Resume, !exps.empty() ? exps.back() : nullptr );
     167}
     168
     169Statement *build_resume_at( ExpressionNode *ctl, ExpressionNode *target ) {
     170        std::list< Expression * > exps;
     171        buildMoveList( ctl, exps );
     172        assertf( exps.size() < 2, "This means we are leaking memory");
     173        return new ThrowStmt( noLabels, ThrowStmt::Resume, !exps.empty() ? exps.back() : nullptr );
    159174}
    160175
     
    166181        return new TryStmt( noLabels, tryBlock, branches, finallyBlock );
    167182}
    168 Statement *build_catch( DeclarationNode *decl, StatementNode *stmt, bool catchAny ) {
    169         std::list< Statement * > branches;
    170         buildMoveList< Statement, StatementNode >( stmt, branches );
    171         assert( branches.size() == 1 );
    172         return new CatchStmt( noLabels, maybeMoveBuild< Declaration >(decl), branches.front(), catchAny );
     183Statement *build_catch( CatchStmt::Kind kind, DeclarationNode *decl, ExpressionNode *cond, StatementNode *body ) {
     184        std::list< Statement * > branches;
     185        buildMoveList< Statement, StatementNode >( body, branches );
     186        assert( branches.size() == 1 );
     187        return new CatchStmt( noLabels, kind, maybeMoveBuild< Declaration >(decl), maybeMoveBuild< Expression >(cond), branches.front() );
    173188}
    174189Statement *build_finally( StatementNode *stmt ) {
  • src/Parser/parser.yy

    r82ff584 ra724ac1  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu May 25 15:21:59 2017
    13 // Update Count     : 2398
     12// Last Modified On : Mon Jun 12 12:59:00 2017
     13// Update Count     : 2402
    1414//
    1515
     
    193193%type<sn> case_value_list                               case_label                                      case_label_list
    194194%type<sn> switch_clause_list_opt                switch_clause_list                      choose_clause_list_opt          choose_clause_list
    195 %type<sn> handler_list                                  handler_clause                          finally_clause
     195%type<sn> /* handler_list */                    handler_clause                          finally_clause
    196196
    197197// declarations
     
    931931                { $$ = new StatementNode( build_throw( $2 ) ); }
    932932        | THROWRESUME assignment_expression_opt ';'                     // handles reresume
    933                 { $$ = new StatementNode( build_throw( $2 ) ); }
     933                { $$ = new StatementNode( build_resume( $2 ) ); }
    934934        | THROWRESUME assignment_expression_opt AT assignment_expression ';' // handles reresume
    935                 { $$ = new StatementNode( build_throw( $2 ) ); }
     935                { $$ = new StatementNode( build_resume_at( $2, $4 ) ); }
    936936        ;
    937937
    938938exception_statement:
    939         TRY compound_statement handler_list
     939        TRY compound_statement handler_clause
    940940                { $$ = new StatementNode( build_try( $2, $3, 0 ) ); }
    941941        | TRY compound_statement finally_clause
    942942                { $$ = new StatementNode( build_try( $2, 0, $3 ) ); }
    943         | TRY compound_statement handler_list finally_clause
     943        | TRY compound_statement handler_clause finally_clause
    944944                { $$ = new StatementNode( build_try( $2, $3, $4 ) ); }
    945945        ;
    946946
    947 handler_list:
    948         handler_clause
    949                 // ISO/IEC 9899:1999 Section 15.3(6 ) If present, a "..." handler shall be the last handler for its try block.
    950         | CATCH '(' ELLIPSIS ')' compound_statement
    951                 { $$ = new StatementNode( build_catch( 0, $5, true ) ); }
    952         | handler_clause CATCH '(' ELLIPSIS ')' compound_statement
    953                 { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( 0, $6, true ) ) ); }
    954         | CATCHRESUME '(' ELLIPSIS ')' compound_statement
    955                 { $$ = new StatementNode( build_catch( 0, $5, true ) ); }
    956         | handler_clause CATCHRESUME '(' ELLIPSIS ')' compound_statement
    957                 { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( 0, $6, true ) ) ); }
    958         ;
     947//handler_list:
     948//      handler_clause
     949//              // ISO/IEC 9899:1999 Section 15.3(6 ) If present, a "..." handler shall be the last handler for its try block.
     950//      | CATCH '(' ELLIPSIS ')' compound_statement
     951//              { $$ = new StatementNode( build_catch( 0, $5, true ) ); }
     952//      | handler_clause CATCH '(' ELLIPSIS ')' compound_statement
     953//              { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( 0, $6, true ) ) ); }
     954//      | CATCHRESUME '(' ELLIPSIS ')' compound_statement
     955//              { $$ = new StatementNode( build_catch( 0, $5, true ) ); }
     956//      | handler_clause CATCHRESUME '(' ELLIPSIS ')' compound_statement
     957//              { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( 0, $6, true ) ) ); }
     958//      ;
    959959
    960960handler_clause:
    961961        CATCH '(' push push exception_declaration pop ')' compound_statement pop
    962                 { $$ = new StatementNode( build_catch( $5, $8 ) ); }
     962                { $$ = new StatementNode( build_catch( CatchStmt::Terminate, $5, nullptr, $8 ) ); }
    963963        | handler_clause CATCH '(' push push exception_declaration pop ')' compound_statement pop
    964                 { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( $6, $9 ) ) ); }
     964                { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( CatchStmt::Terminate, $6, nullptr, $9 ) ) ); }
    965965        | CATCHRESUME '(' push push exception_declaration pop ')' compound_statement pop
    966                 { $$ = new StatementNode( build_catch( $5, $8 ) ); }
     966                { $$ = new StatementNode( build_catch( CatchStmt::Resume, $5, nullptr, $8 ) ); }
    967967        | handler_clause CATCHRESUME '(' push push exception_declaration pop ')' compound_statement pop
    968                 { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( $6, $9 ) ) ); }
     968                { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( CatchStmt::Resume, $6, nullptr, $9 ) ) ); }
    969969        ;
    970970
  • src/ResolvExpr/Unify.cc

    r82ff584 ra724ac1  
    683683
    684684        template< typename Iterator1, typename Iterator2 >
    685         bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     685        bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    686686                auto get_type = [](Type * t) { return t; };
    687687                for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
     
    733733                        flatten( flat2.get(), back_inserter( types2 ) );
    734734
    735                         result = unifyList( types1.begin(), types1.end(), types2.begin(), types2.end(), env, needAssertions, haveAssertions, openVars, widenMode, indexer );
     735                        result = unifyList( types1.begin(), types1.end(), types2.begin(), types2.end(), env, needAssertions, haveAssertions, openVars, indexer );
    736736                } // if
    737737        }
  • src/SynTree/Mutator.cc

    r82ff584 ra724ac1  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Mar 30 16:45:19 2017
    13 // Update Count     : 22
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thu Mar  8 16:36:00 2017
     13// Update Count     : 23
    1414//
    1515
     
    153153}
    154154
     155Statement *Mutator::mutate( ThrowStmt *throwStmt ) {
     156        throwStmt->set_expr( maybeMutate( throwStmt->get_expr(), *this ) );
     157        throwStmt->set_target( maybeMutate( throwStmt->get_target(), *this ) );
     158        return throwStmt;
     159}
     160
    155161Statement *Mutator::mutate( TryStmt *tryStmt ) {
    156162        tryStmt->set_block( maybeMutate( tryStmt->get_block(), *this ) );
  • src/SynTree/Mutator.h

    r82ff584 ra724ac1  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  9 14:23:23 2017
    13 // Update Count     : 13
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thu Jun  8 15:45:00 2017
     13// Update Count     : 14
    1414//
    1515#include <cassert>
     
    4646        virtual Statement* mutate( BranchStmt *branchStmt );
    4747        virtual Statement* mutate( ReturnStmt *returnStmt );
    48         virtual Statement* mutate( TryStmt *returnStmt );
     48        virtual Statement* mutate( ThrowStmt *throwStmt );
     49        virtual Statement* mutate( TryStmt *tryStmt );
    4950        virtual Statement* mutate( CatchStmt *catchStmt );
    5051        virtual Statement* mutate( FinallyStmt *catchStmt );
  • src/SynTree/Statement.cc

    r82ff584 ra724ac1  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Aug 12 13:58:48 2016
    13 // Update Count     : 62
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Jun 12 10:37:00 2017
     13// Update Count     : 64
    1414//
    1515
     
    101101}
    102102
    103 ReturnStmt::ReturnStmt( std::list<Label> labels, Expression *_expr, bool throwP ) : Statement( labels ), expr( _expr ), isThrow( throwP ) {}
    104 
    105 ReturnStmt::ReturnStmt( const ReturnStmt & other ) : Statement( other ), expr( maybeClone( other.expr ) ), isThrow( other.isThrow ) {}
     103ReturnStmt::ReturnStmt( std::list<Label> labels, Expression *_expr ) : Statement( labels ), expr( _expr ) {}
     104
     105ReturnStmt::ReturnStmt( const ReturnStmt & other ) : Statement( other ), expr( maybeClone( other.expr ) ) {}
    106106
    107107ReturnStmt::~ReturnStmt() {
     
    110110
    111111void ReturnStmt::print( std::ostream &os, int indent ) const {
    112         os << string ( isThrow? "Throw":"Return" ) << " Statement, returning: ";
     112        os <<  "Return Statement, returning: ";
    113113        if ( expr != 0 ) {
    114114                os << endl << string( indent+2, ' ' );
     
    287287}
    288288
     289ThrowStmt::ThrowStmt( std::list<Label> labels, Kind kind, Expression * expr, Expression * target ) :
     290                Statement( labels ), kind(kind), expr(expr), target(target)     {
     291        assertf(Resume == kind || nullptr == target, "Non-local termination throw is not accepted." );
     292}
     293
     294ThrowStmt::ThrowStmt( const ThrowStmt &other ) :
     295        Statement ( other ), kind( other.kind ), expr( maybeClone( other.expr ) ), target( maybeClone( other.target ) ) {
     296}
     297
     298ThrowStmt::~ThrowStmt() {
     299        delete expr;
     300        delete target;
     301}
     302
     303void ThrowStmt::print( std::ostream &os, int indent) const {
     304        if ( target ) {
     305                os << "Non-Local ";
     306        }
     307        os << "Throw Statement, raising: ";
     308        expr->print(os, indent + 4);
     309        if ( target ) {
     310                os << "At: ";
     311                target->print(os, indent + 4);
     312        }
     313}
     314
    289315TryStmt::TryStmt( std::list<Label> labels, CompoundStmt *tryBlock, std::list<Statement *> &_handlers, FinallyStmt *_finallyBlock ) :
    290316        Statement( labels ), block( tryBlock ),  handlers( _handlers ), finallyBlock( _finallyBlock ) {
     
    318344}
    319345
    320 CatchStmt::CatchStmt( std::list<Label> labels, Declaration *_decl, Statement *_body, bool catchAny ) :
    321         Statement( labels ), decl ( _decl ), body( _body ), catchRest ( catchAny ) {
     346CatchStmt::CatchStmt( std::list<Label> labels, Kind _kind, Declaration *_decl, Expression *_cond, Statement *_body ) :
     347        Statement( labels ), kind ( _kind ), decl ( _decl ), cond ( _cond ), body( _body ) {
    322348}
    323349
    324350CatchStmt::CatchStmt( const CatchStmt & other ) :
    325         Statement( other ), decl ( maybeClone( other.decl ) ), body( maybeClone( other.body ) ), catchRest ( other.catchRest ) {
     351        Statement( other ), kind ( other.kind ), decl ( maybeClone( other.decl ) ), cond ( maybeClone( other.cond ) ), body( maybeClone( other.body ) ) {
    326352}
    327353
     
    332358
    333359void CatchStmt::print( std::ostream &os, int indent ) const {
    334         os << "Catch Statement" << endl;
     360        os << "Catch " << ((Terminate == kind) ? "Terminate" : "Resume") << " Statement" << endl;
    335361
    336362        os << string( indent, ' ' ) << "... catching" << endl;
     
    338364                decl->printShort( os, indent + 4 );
    339365                os << endl;
    340         } else if ( catchRest )
    341                 os << string( indent + 4 , ' ' ) << "the rest" << endl;
     366        }
    342367        else
    343368                os << string( indent + 4 , ' ' ) << ">>> Error:  this catch clause must have a declaration <<<" << endl;
  • src/SynTree/Statement.h

    r82ff584 ra724ac1  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Aug 12 13:57:46 2016
    13 // Update Count     : 65
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Jun 12 13:35:00 2017
     13// Update Count     : 67
    1414//
    1515
     
    5757  private:
    5858        std::list<Statement*> kids;
     59};
     60
     61class NullStmt : public CompoundStmt {
     62  public:
     63        NullStmt();
     64        NullStmt( std::list<Label> labels );
     65
     66        virtual NullStmt *clone() const { return new NullStmt( *this ); }
     67        virtual void accept( Visitor &v ) { v.visit( this ); }
     68        virtual NullStmt *acceptMutator( Mutator &m ) { return m.mutate( this ); }
     69        virtual void print( std::ostream &os, int indent = 0 ) const;
     70
     71  private:
    5972};
    6073
     
    261274class ReturnStmt : public Statement {
    262275  public:
    263         ReturnStmt( std::list<Label> labels, Expression *expr, bool throwP = false );
     276        ReturnStmt( std::list<Label> labels, Expression *expr );
    264277        ReturnStmt( const ReturnStmt &other );
    265278        virtual ~ReturnStmt();
     
    274287  private:
    275288        Expression *expr;
    276         bool isThrow;
    277 };
    278 
    279 
    280 class NullStmt : public CompoundStmt {
    281   public:
    282         NullStmt();
    283         NullStmt( std::list<Label> labels );
    284 
    285         virtual NullStmt *clone() const { return new NullStmt( *this ); }
    286         virtual void accept( Visitor &v ) { v.visit( this ); }
    287         virtual NullStmt *acceptMutator( Mutator &m ) { return m.mutate( this ); }
    288         virtual void print( std::ostream &os, int indent = 0 ) const;
    289 
    290   private:
     289};
     290
     291class ThrowStmt : public Statement {
     292  public:
     293        enum Kind { Terminate, Resume };
     294
     295        ThrowStmt( std::list<Label> labels, Kind kind, Expression * expr, Expression * target = nullptr );
     296        ThrowStmt( const ThrowStmt &other );
     297        virtual ~ThrowStmt();
     298
     299        Kind get_kind() { return kind; }
     300        Expression * get_expr() { return expr; }
     301        void set_expr( Expression * newExpr ) { expr = newExpr; }
     302        Expression * get_target() { return target; }
     303        void set_target( Expression * newTarget ) { target = newTarget; }
     304
     305        virtual ThrowStmt *clone() const { return new ThrowStmt( *this ); }
     306        virtual void accept( Visitor &v ) { v.visit( this ); }
     307        virtual Statement *acceptMutator( Mutator &m ) { return m.mutate( this ); }
     308        virtual void print( std::ostream &os, int indent = 0 ) const;
     309  private:
     310        Kind kind;
     311        Expression * expr;
     312        Expression * target;
    291313};
    292314
     
    317339class CatchStmt : public Statement {
    318340  public:
    319         CatchStmt( std::list<Label> labels, Declaration *decl, Statement *body, bool catchAny = false );
     341        enum Kind { Terminate, Resume };
     342
     343        CatchStmt( std::list<Label> labels, Kind kind, Declaration *decl,
     344                   Expression *cond, Statement *body );
    320345        CatchStmt( const CatchStmt &other );
    321346        virtual ~CatchStmt();
    322347
     348        Kind get_kind() { return kind; }
    323349        Declaration *get_decl() { return decl; }
    324350        void set_decl( Declaration *newValue ) { decl = newValue; }
    325 
     351        Expression *get_cond() { return cond; }
     352        void set_cond( Expression *newCond ) { cond = newCond; }
    326353        Statement *get_body() { return body; }
    327354        void set_body( Statement *newValue ) { body = newValue; }
     
    333360
    334361  private:
     362        Kind kind;
    335363        Declaration *decl;
     364        Expression *cond;
    336365        Statement *body;
    337         bool catchRest;
    338366};
    339367
  • src/SynTree/SynTree.h

    r82ff584 ra724ac1  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  9 14:23:49 2017
    13 // Update Count     : 8
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thu Jun  8 17:00:00 2017
     13// Update Count     : 9
    1414//
    1515
     
    5151class BranchStmt;
    5252class ReturnStmt;
     53class ThrowStmt;
    5354class TryStmt;
    5455class CatchStmt;
  • src/SynTree/Visitor.cc

    r82ff584 ra724ac1  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Mar 30 16:45:25 2017
    13 // Update Count     : 24
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thu Jun  8 16:31:00 2017
     13// Update Count     : 25
    1414//
    1515
     
    129129}
    130130
     131void Visitor::visit( ThrowStmt * throwStmt ) {
     132        maybeAccept( throwStmt->get_expr(), *this );
     133        maybeAccept( throwStmt->get_target(), *this );
     134}
     135
    131136void Visitor::visit( TryStmt *tryStmt ) {
    132137        maybeAccept( tryStmt->get_block(), *this );
  • src/SynTree/Visitor.h

    r82ff584 ra724ac1  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed May  3 08:58:00 2017
    13 // Update Count     : 10
     12// Last Modified On : Thr Jun 08 15:45:00 2017
     13// Update Count     : 11
    1414//
    1515
     
    4949        virtual void visit( BranchStmt *branchStmt );
    5050        virtual void visit( ReturnStmt *returnStmt );
     51        virtual void visit( ThrowStmt *throwStmt );
    5152        virtual void visit( TryStmt *tryStmt );
    5253        virtual void visit( CatchStmt *catchStmt );
  • tools/cfa.nanorc

    r82ff584 ra724ac1  
    3333## Update/Redistribute
    3434# GCC builtins
    35 ##color cyan "__attribute__[[:space:]]*\(\([^)]*\)\)" "__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
     35color cyan "__attribute__[[:space:]]*\(\([^()]*(\([^()]*\)[^()]*)*\)\)"
     36##color cyan "__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
    3637
    3738# Preprocesser Directives
Note: See TracChangeset for help on using the changeset viewer.