Changeset cde3891 for src


Ignore:
Timestamp:
Jan 23, 2019, 4:52:16 PM (7 years ago)
Author:
Thierry Delisle <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:
a200795
Parents:
9b086ca (diff), 1d832f4 (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' into cleanup-dtors

Location:
src
Files:
7 added
51 edited

Legend:

Unmodified
Added
Removed
  • src/CodeTools/module.mk

    r9b086ca rcde3891  
    1616
    1717SRC += CodeTools/DeclStats.cc \
     18        CodeTools/ResolvProtoDump.cc \
    1819        CodeTools/TrackLoc.cc
  • src/Common/utility.h

    r9b086ca rcde3891  
    2626#include <string>
    2727#include <type_traits>
     28#include <utility>
    2829
    2930#include <cassert>
     
    462463std::pair<long long int, bool> eval(Expression * expr);
    463464
     465// -----------------------------------------------------------------------------
     466/// Reorders the input range in-place so that the minimal-value elements according to the
     467/// comparator are in front;
     468/// returns the iterator after the last minimal-value element.
     469template<typename Iter, typename Compare>
     470Iter sort_mins( Iter begin, Iter end, Compare& lt ) {
     471        if ( begin == end ) return end;
     472       
     473        Iter min_pos = begin;
     474        for ( Iter i = begin + 1; i != end; ++i ) {
     475                if ( lt( *i, *min_pos ) ) {
     476                        // new minimum cost; swap into first position
     477                        min_pos = begin;
     478                        std::iter_swap( min_pos, i );
     479                } else if ( ! lt( *min_pos, *i ) ) {
     480                        // duplicate minimum cost; swap into next minimum position
     481                        ++min_pos;
     482                        std::iter_swap( min_pos, i );
     483                }
     484        }
     485        return ++min_pos;
     486}
     487
     488template<typename Iter, typename Compare>
     489inline Iter sort_mins( Iter begin, Iter end, Compare&& lt ) {
     490        return sort_mins( begin, end, lt );
     491}
     492
     493/// sort_mins defaulted to use std::less
     494template<typename Iter>
     495inline Iter sort_mins( Iter begin, Iter end ) {
     496        return sort_mins( begin, end, std::less<typename std::iterator_traits<Iter>::value_type>{} );
     497}
     498
    464499// Local Variables: //
    465500// tab-width: 4 //
  • src/CompilationState.cc

    r9b086ca rcde3891  
    3030        parsep = false,
    3131        resolvep = false,
     32        resolvprotop = false,
    3233        symtabp = false,
    3334        treep = false,
  • src/CompilationState.h

    r9b086ca rcde3891  
    3131        parsep,
    3232        resolvep,
     33        resolvprotop,
    3334        symtabp,
    3435        treep,
  • src/Concurrency/Keywords.cc

    r9b086ca rcde3891  
    575575
    576576                //in reverse order :
    577                 // monitor_guard_t __guard = { __monitors, #, func };
     577                // monitor_dtor_guard_t __guard = { __monitors, func };
    578578                body->push_front(
    579579                        new DeclStmt( new ObjectDecl(
     
    634634                assert(generic_func);
    635635
    636                 //in reverse order :
     636                // in reverse order :
    637637                // monitor_guard_t __guard = { __monitors, #, func };
    638638                body->push_front(
  • src/Concurrency/Waitfor.cc

    r9b086ca rcde3891  
    6666void foo() {
    6767        while( true ) {
    68 
    69                 acceptable_t acceptables[3];
    70                 if( a < 1 ) {
    71                         acceptables[0].func = f;
    72                         acceptables[0].mon = a;
    73                 }
    74                 acceptables[1].func = g;
    75                 acceptables[1].mon = a;
    76 
    77                 acceptables[2].func = f;
    78                 acceptables[2].mon = a;
    79                 acceptables[2].is_dtor = true;
    80 
    81                 int ret = waitfor_internal( acceptables, swagl() );
    82 
    83                 switch( ret ) {
    84                         case 0:
    85                         {
    86                                 bar();
     68                {
     69                        acceptable_t acceptables[3];
     70                        if( a < 1 ) {
     71                                acceptables[0].func = f;
     72                                acceptables[0].mon = a;
    8773                        }
    88                         case 1:
    89                         {
    90                                 baz();
     74                        acceptables[1].func = g;
     75                        acceptables[1].mon = a;
     76
     77                        acceptables[2].func = f;
     78                        acceptables[2].mon = a;
     79                        acceptables[2].is_dtor = true;
     80
     81                        int ret = waitfor_internal( acceptables, swagl() );
     82
     83                        switch( ret ) {
     84                                case 0:
     85                                {
     86                                        bar();
     87                                }
     88                                case 1:
     89                                {
     90                                        baz();
     91                                }
     92                                case 2:
     93                                        signal(a);
     94                                        {
     95                                                break;
     96                                        }
    9197                        }
    92                         case 2:
    93                                 signal(a);
    94                                 {
    95                                         break;
    96                                 }
    9798                }
    9899        }
     
    555556                                        new ConstantExpr( Constant::from_ulong( i++ ) ),
    556557                                        {
    557                                                 clause.statement,
    558                                                 new BranchStmt(
    559                                                         "",
    560                                                         BranchStmt::Break
    561                                                 )
     558                                                new CompoundStmt({
     559                                                        clause.statement,
     560                                                        new BranchStmt(
     561                                                                "",
     562                                                                BranchStmt::Break
     563                                                        )
     564                                                })
    562565                                        }
    563566                                )
     
    570573                                        new ConstantExpr( Constant::from_int( -2 ) ),
    571574                                        {
    572                                                 waitfor->timeout.statement,
    573                                                 new BranchStmt(
    574                                                         "",
    575                                                         BranchStmt::Break
    576                                                 )
     575                                                new CompoundStmt({
     576                                                        waitfor->timeout.statement,
     577                                                        new BranchStmt(
     578                                                                "",
     579                                                                BranchStmt::Break
     580                                                        )
     581                                                })
    577582                                        }
    578583                                )
     
    585590                                        new ConstantExpr( Constant::from_int( -1 ) ),
    586591                                        {
    587                                                 waitfor->orelse.statement,
    588                                                 new BranchStmt(
    589                                                         "",
    590                                                         BranchStmt::Break
    591                                                 )
     592                                                new CompoundStmt({
     593                                                        waitfor->orelse.statement,
     594                                                        new BranchStmt(
     595                                                                "",
     596                                                                BranchStmt::Break
     597                                                        )
     598                                                })
    592599                                        }
    593600                                )
  • src/GenPoly/Box.cc

    r9b086ca rcde3891  
    798798                        for ( Type::ForallList::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
    799799                                for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->assertions.begin(); assert != (*tyVar)->assertions.end(); ++assert ) {
    800                                         InferredParams::const_iterator inferParam = appExpr->get_inferParams().find( (*assert)->get_uniqueId() );
    801                                         assertf( inferParam != appExpr->get_inferParams().end(), "addInferredParams missing inferred parameter: %s in: %s", toString( *assert ).c_str(), toString( appExpr ).c_str() );
     800                                        InferredParams::const_iterator inferParam = appExpr->inferParams.find( (*assert)->get_uniqueId() );
     801                                        assertf( inferParam != appExpr->inferParams.end(), "addInferredParams missing inferred parameter: %s in: %s", toString( *assert ).c_str(), toString( appExpr ).c_str() );
    802802                                        Expression *newExpr = inferParam->second.expr->clone();
    803803                                        addCast( newExpr, (*assert)->get_type(), tyVars );
  • src/GenPoly/Specialize.cc

    r9b086ca rcde3891  
    245245                appExpr->env = TypeSubstitution::newFromExpr( appExpr, env );
    246246                if ( inferParams ) {
    247                         appExpr->get_inferParams() = *inferParams;
     247                        appExpr->inferParams = *inferParams;
    248248                } // if
    249249
     
    284284                std::list< Expression* >::iterator actual;
    285285                for ( formal = function->get_parameters().begin(), actual = appExpr->get_args().begin(); formal != function->get_parameters().end() && actual != appExpr->get_args().end(); ++formal, ++actual ) {
    286                         *actual = doSpecialization( (*formal)->get_type(), *actual, &appExpr->get_inferParams() );
     286                        *actual = doSpecialization( (*formal)->get_type(), *actual, &appExpr->inferParams );
    287287                }
    288288        }
     
    295295                        // alternatively, if order starts to matter then copy appExpr's inferParams and pass them to handleExplicitParams.
    296296                        handleExplicitParams( appExpr );
    297                         for ( InferredParams::iterator inferParam = appExpr->get_inferParams().begin(); inferParam != appExpr->get_inferParams().end(); ++inferParam ) {
    298                                 inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, inferParam->second.inferParams.get() );
     297                        for ( InferredParams::iterator inferParam = appExpr->inferParams.begin(); inferParam != appExpr->inferParams.end(); ++inferParam ) {
     298                                inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, &inferParam->second.expr->inferParams );
    299299                        }
    300300                }
  • src/Makefile.am

    r9b086ca rcde3891  
    1717# create object files in directory with source files
    1818AUTOMAKE_OPTIONS = foreign subdir-objects
     19ACLOCAL_AMFLAGS  = -I automake
    1920
    2021SRC = main.cc \
     
    5051AM_CXXFLAGS = @HOST_FLAGS@ -Wno-deprecated -Wall -Wextra -DDEBUG_ALL -I./Parser -I$(srcdir)/Parser -I$(srcdir)/include -DYY_NO_INPUT -O2 -g -std=c++14
    5152AM_LDFLAGS  = @HOST_FLAGS@ -Xlinker -export-dynamic
     53ARFLAGS     = cr
    5254
    5355demangler_SOURCES = SymTab/demangler.cc # test driver for the demangler, also useful as a sanity check that libdemangle.a is complete
     
    126128  ResolvExpr/PtrsCastable.cc \
    127129  ResolvExpr/RenameVars.cc \
     130  ResolvExpr/ResolveAssertions.cc \
    128131  ResolvExpr/Resolver.cc \
    129132  ResolvExpr/ResolveTypeof.cc \
     133  ResolvExpr/SpecCost.cc \
    130134  ResolvExpr/TypeEnvironment.cc \
    131135  ResolvExpr/Unify.cc \
  • src/Makefile.in

    r9b086ca rcde3891  
    141141subdir = src
    142142ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
    143 am__aclocal_m4_deps = $(top_srcdir)/automake/cfa.m4 \
    144         $(top_srcdir)/configure.ac
     143am__aclocal_m4_deps = $(top_srcdir)/automake/libtool.m4 \
     144        $(top_srcdir)/automake/ltoptions.m4 \
     145        $(top_srcdir)/automake/ltsugar.m4 \
     146        $(top_srcdir)/automake/ltversion.m4 \
     147        $(top_srcdir)/automake/lt~obsolete.m4 \
     148        $(top_srcdir)/automake/cfa.m4 $(top_srcdir)/configure.ac
    145149am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
    146150        $(ACLOCAL_M4)
     
    151155CONFIG_CLEAN_VPATH_FILES =
    152156LIBRARIES = $(noinst_LIBRARIES)
    153 AR = ar
    154 ARFLAGS = cru
    155157AM_V_AR = $(am__v_AR_@AM_V@)
    156158am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@)
     
    204206        ResolvExpr/PtrsAssignable.$(OBJEXT) \
    205207        ResolvExpr/PtrsCastable.$(OBJEXT) \
    206         ResolvExpr/RenameVars.$(OBJEXT) ResolvExpr/Resolver.$(OBJEXT) \
     208        ResolvExpr/RenameVars.$(OBJEXT) \
     209        ResolvExpr/ResolveAssertions.$(OBJEXT) \
     210        ResolvExpr/Resolver.$(OBJEXT) \
    207211        ResolvExpr/ResolveTypeof.$(OBJEXT) \
     212        ResolvExpr/SpecCost.$(OBJEXT) \
    208213        ResolvExpr/TypeEnvironment.$(OBJEXT) \
    209214        ResolvExpr/Unify.$(OBJEXT) SymTab/Autogen.$(OBJEXT) \
     
    222227        CodeGen/FixNames.$(OBJEXT) CodeGen/FixMain.$(OBJEXT) \
    223228        CodeGen/OperatorTable.$(OBJEXT) CodeTools/DeclStats.$(OBJEXT) \
     229        CodeTools/ResolvProtoDump.$(OBJEXT) \
    224230        CodeTools/TrackLoc.$(OBJEXT) Concurrency/Keywords.$(OBJEXT) \
    225231        Concurrency/Waitfor.$(OBJEXT) Common/SemanticError.$(OBJEXT) \
     
    260266        ResolvExpr/TypeEnvironment.$(OBJEXT) \
    261267        ResolvExpr/CurrentObject.$(OBJEXT) \
    262         ResolvExpr/ExplodedActual.$(OBJEXT) SymTab/Indexer.$(OBJEXT) \
    263         SymTab/Mangler.$(OBJEXT) SymTab/ManglerCommon.$(OBJEXT) \
    264         SymTab/Validate.$(OBJEXT) SymTab/FixFunction.$(OBJEXT) \
    265         SymTab/Autogen.$(OBJEXT) SynTree/Type.$(OBJEXT) \
    266         SynTree/VoidType.$(OBJEXT) SynTree/BasicType.$(OBJEXT) \
    267         SynTree/PointerType.$(OBJEXT) SynTree/ArrayType.$(OBJEXT) \
    268         SynTree/ReferenceType.$(OBJEXT) SynTree/FunctionType.$(OBJEXT) \
     268        ResolvExpr/ExplodedActual.$(OBJEXT) \
     269        ResolvExpr/SpecCost.$(OBJEXT) \
     270        ResolvExpr/ResolveAssertions.$(OBJEXT) \
     271        SymTab/Indexer.$(OBJEXT) SymTab/Mangler.$(OBJEXT) \
     272        SymTab/ManglerCommon.$(OBJEXT) SymTab/Validate.$(OBJEXT) \
     273        SymTab/FixFunction.$(OBJEXT) SymTab/Autogen.$(OBJEXT) \
     274        SynTree/Type.$(OBJEXT) SynTree/VoidType.$(OBJEXT) \
     275        SynTree/BasicType.$(OBJEXT) SynTree/PointerType.$(OBJEXT) \
     276        SynTree/ArrayType.$(OBJEXT) SynTree/ReferenceType.$(OBJEXT) \
     277        SynTree/FunctionType.$(OBJEXT) \
    269278        SynTree/ReferenceToType.$(OBJEXT) SynTree/TupleType.$(OBJEXT) \
    270279        SynTree/TypeofType.$(OBJEXT) SynTree/AttrType.$(OBJEXT) \
     
    291300___driver_cfa_cpp_OBJECTS = $(am____driver_cfa_cpp_OBJECTS)
    292301___driver_cfa_cpp_DEPENDENCIES =
     302AM_V_lt = $(am__v_lt_@AM_V@)
     303am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
     304am__v_lt_0 = --silent
     305am__v_lt_1 =
    293306am_demangler_OBJECTS = SymTab/demangler.$(OBJEXT)
    294307demangler_OBJECTS = $(am_demangler_OBJECTS)
     
    312325CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
    313326        $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
     327LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
     328        $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
     329        $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
     330        $(AM_CXXFLAGS) $(CXXFLAGS)
    314331AM_V_CXX = $(am__v_CXX_@AM_V@)
    315332am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
     
    317334am__v_CXX_1 =
    318335CXXLD = $(CXX)
    319 CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
    320         -o $@
     336CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
     337        $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
     338        $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
    321339AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
    322340am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
     
    324342am__v_CXXLD_1 =
    325343LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS)
     344LTLEXCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
     345        $(LIBTOOLFLAGS) --mode=compile $(LEX) $(AM_LFLAGS) $(LFLAGS)
    326346AM_V_LEX = $(am__v_LEX_@AM_V@)
    327347am__v_LEX_ = $(am__v_LEX_@AM_DEFAULT_V@)
     
    332352                   -e s/c++$$/h++/ -e s/c$$/h/
    333353YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS)
     354LTYACCCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
     355        $(LIBTOOLFLAGS) --mode=compile $(YACC) $(AM_YFLAGS) $(YFLAGS)
    334356AM_V_YACC = $(am__v_YACC_@AM_V@)
    335357am__v_YACC_ = $(am__v_YACC_@AM_DEFAULT_V@)
     
    338360COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
    339361        $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
     362LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
     363        $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
     364        $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
     365        $(AM_CFLAGS) $(CFLAGS)
    340366AM_V_CC = $(am__v_CC_@AM_V@)
    341367am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
     
    343369am__v_CC_1 =
    344370CCLD = $(CC)
    345 LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
     371LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
     372        $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
     373        $(AM_LDFLAGS) $(LDFLAGS) -o $@
    346374AM_V_CCLD = $(am__v_CCLD_@AM_V@)
    347375am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
     
    393421AMTAR = @AMTAR@
    394422AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
     423AR = @AR@
    395424AUTOCONF = @AUTOCONF@
    396425AUTOHEADER = @AUTOHEADER@
    397426AUTOMAKE = @AUTOMAKE@
    398427AWK = @AWK@
    399 BACKEND_CC = @BACKEND_CC@
    400428BUILD_IN_TREE_FLAGS = @BUILD_IN_TREE_FLAGS@
    401429CC = @CC@
     
    417445CPPFLAGS = @CPPFLAGS@
    418446CXX = @CXX@
     447CXXCPP = @CXXCPP@
    419448CXXDEPMODE = @CXXDEPMODE@
    420449CXXFLAGS = @CXXFLAGS@
     
    422451DEFS = @DEFS@
    423452DEPDIR = @DEPDIR@
     453DLLTOOL = @DLLTOOL@
    424454DRIVER_DIR = @DRIVER_DIR@
     455DSYMUTIL = @DSYMUTIL@
     456DUMPBIN = @DUMPBIN@
    425457ECHO_C = @ECHO_C@
    426458ECHO_N = @ECHO_N@
     
    428460EGREP = @EGREP@
    429461EXEEXT = @EXEEXT@
     462FGREP = @FGREP@
    430463GREP = @GREP@
    431464HOST_FLAGS = @HOST_FLAGS@
     
    435468INSTALL_SCRIPT = @INSTALL_SCRIPT@
    436469INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
     470LD = @LD@
    437471LDFLAGS = @LDFLAGS@
    438472LEX = @LEX@
     
    443477LIBOBJS = @LIBOBJS@
    444478LIBS = @LIBS@
     479LIBTOOL = @LIBTOOL@
     480LIPO = @LIPO@
     481LN_S = @LN_S@
    445482LTLIBOBJS = @LTLIBOBJS@
     483LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
    446484MAKEINFO = @MAKEINFO@
     485MANIFEST_TOOL = @MANIFEST_TOOL@
    447486MKDIR_P = @MKDIR_P@
     487NM = @NM@
     488NMEDIT = @NMEDIT@
     489OBJDUMP = @OBJDUMP@
    448490OBJEXT = @OBJEXT@
     491OTOOL = @OTOOL@
     492OTOOL64 = @OTOOL64@
    449493PACKAGE = @PACKAGE@
    450494PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
     
    456500PATH_SEPARATOR = @PATH_SEPARATOR@
    457501RANLIB = @RANLIB@
     502SED = @SED@
    458503SET_MAKE = @SET_MAKE@
    459504SHELL = @SHELL@
     
    467512abs_top_builddir = @abs_top_builddir@
    468513abs_top_srcdir = @abs_top_srcdir@
     514ac_ct_AR = @ac_ct_AR@
    469515ac_ct_CC = @ac_ct_CC@
    470516ac_ct_CXX = @ac_ct_CXX@
     517ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
    471518am__include = @am__include@
    472519am__leading_dot = @am__leading_dot@
     
    518565# create object files in directory with source files
    519566AUTOMAKE_OPTIONS = foreign subdir-objects
     567ACLOCAL_AMFLAGS = -I automake
    520568SRC = main.cc MakeLibCfa.cc CompilationState.cc CodeGen/Generate.cc \
    521569        CodeGen/CodeGenerator.cc CodeGen/GenType.cc \
    522570        CodeGen/FixNames.cc CodeGen/FixMain.cc \
    523571        CodeGen/OperatorTable.cc CodeTools/DeclStats.cc \
    524         CodeTools/TrackLoc.cc Concurrency/Keywords.cc \
    525         Concurrency/Waitfor.cc Common/SemanticError.cc \
    526         Common/UniqueName.cc Common/DebugMalloc.cc Common/Assert.cc \
    527         Common/Heap.cc Common/Eval.cc ControlStruct/LabelGenerator.cc \
     572        CodeTools/ResolvProtoDump.cc CodeTools/TrackLoc.cc \
     573        Concurrency/Keywords.cc Concurrency/Waitfor.cc \
     574        Common/SemanticError.cc Common/UniqueName.cc \
     575        Common/DebugMalloc.cc Common/Assert.cc Common/Heap.cc \
     576        Common/Eval.cc ControlStruct/LabelGenerator.cc \
    528577        ControlStruct/LabelFixer.cc ControlStruct/MLEMutator.cc \
    529578        ControlStruct/Mutate.cc ControlStruct/ForExprMutator.cc \
     
    548597        ResolvExpr/Occurs.cc ResolvExpr/TypeEnvironment.cc \
    549598        ResolvExpr/CurrentObject.cc ResolvExpr/ExplodedActual.cc \
     599        ResolvExpr/SpecCost.cc ResolvExpr/ResolveAssertions.cc \
    550600        SymTab/Indexer.cc SymTab/Mangler.cc SymTab/ManglerCommon.cc \
    551601        SymTab/Validate.cc SymTab/FixFunction.cc SymTab/Autogen.cc \
     
    582632AM_CXXFLAGS = @HOST_FLAGS@ -Wno-deprecated -Wall -Wextra -DDEBUG_ALL -I./Parser -I$(srcdir)/Parser -I$(srcdir)/include -DYY_NO_INPUT -O2 -g -std=c++14
    583633AM_LDFLAGS = @HOST_FLAGS@ -Xlinker -export-dynamic
     634ARFLAGS = cr
    584635demangler_SOURCES = SymTab/demangler.cc # test driver for the demangler, also useful as a sanity check that libdemangle.a is complete
    585636demangler_LDADD = libdemangle.a     # yywrap
     
    655706  ResolvExpr/PtrsCastable.cc \
    656707  ResolvExpr/RenameVars.cc \
     708  ResolvExpr/ResolveAssertions.cc \
    657709  ResolvExpr/Resolver.cc \
    658710  ResolvExpr/ResolveTypeof.cc \
     711  ResolvExpr/SpecCost.cc \
    659712  ResolvExpr/TypeEnvironment.cc \
    660713  ResolvExpr/Unify.cc \
     
    674727
    675728.SUFFIXES:
    676 .SUFFIXES: .cc .ll .o .obj .yy
     729.SUFFIXES: .cc .ll .lo .o .obj .yy
    677730$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am $(srcdir)/CodeGen/module.mk $(srcdir)/CodeTools/module.mk $(srcdir)/Concurrency/module.mk $(srcdir)/Common/module.mk $(srcdir)/ControlStruct/module.mk $(srcdir)/GenPoly/module.mk $(srcdir)/InitTweak/module.mk $(srcdir)/Parser/module.mk $(srcdir)/ResolvExpr/module.mk $(srcdir)/SymTab/module.mk $(srcdir)/SynTree/module.mk $(srcdir)/Tuples/module.mk $(srcdir)/Validate/module.mk $(srcdir)/Virtual/module.mk $(am__configure_deps)
    678731        @for dep in $?; do \
     
    908961ResolvExpr/RenameVars.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    909962        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     963ResolvExpr/ResolveAssertions.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     964        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    910965ResolvExpr/Resolver.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    911966        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    912967ResolvExpr/ResolveTypeof.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     968        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     969ResolvExpr/SpecCost.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    913970        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    914971ResolvExpr/TypeEnvironment.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     
    9631020        sed 's/$(EXEEXT)$$//' | \
    9641021        while read p p1; do if test -f $$p \
     1022         || test -f $$p1 \
    9651023          ; then echo "$$p"; echo "$$p"; else :; fi; \
    9661024        done | \
     
    9771035            if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
    9781036            test -z "$$files" || { \
    979               echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(cfa_cpplibdir)$$dir'"; \
    980               $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(cfa_cpplibdir)$$dir" || exit $$?; \
     1037            echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(cfa_cpplibdir)$$dir'"; \
     1038            $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(cfa_cpplibdir)$$dir" || exit $$?; \
    9811039            } \
    9821040        ; done
     
    9941052
    9951053clean-cfa_cpplibPROGRAMS:
    996         -test -z "$(cfa_cpplib_PROGRAMS)" || rm -f $(cfa_cpplib_PROGRAMS)
     1054        @list='$(cfa_cpplib_PROGRAMS)'; test -n "$$list" || exit 0; \
     1055        echo " rm -f" $$list; \
     1056        rm -f $$list || exit $$?; \
     1057        test -n "$(EXEEXT)" || exit 0; \
     1058        list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
     1059        echo " rm -f" $$list; \
     1060        rm -f $$list
    9971061CodeGen/FixNames.$(OBJEXT): CodeGen/$(am__dirstamp) \
    9981062        CodeGen/$(DEPDIR)/$(am__dirstamp)
     
    10041068        @: > CodeTools/$(DEPDIR)/$(am__dirstamp)
    10051069CodeTools/DeclStats.$(OBJEXT): CodeTools/$(am__dirstamp) \
     1070        CodeTools/$(DEPDIR)/$(am__dirstamp)
     1071CodeTools/ResolvProtoDump.$(OBJEXT): CodeTools/$(am__dirstamp) \
    10061072        CodeTools/$(DEPDIR)/$(am__dirstamp)
    10071073CodeTools/TrackLoc.$(OBJEXT): CodeTools/$(am__dirstamp) \
     
    11071173@AMDEP_TRUE@@am__include@ @am__quote@CodeGen/$(DEPDIR)/OperatorTable.Po@am__quote@
    11081174@AMDEP_TRUE@@am__include@ @am__quote@CodeTools/$(DEPDIR)/DeclStats.Po@am__quote@
     1175@AMDEP_TRUE@@am__include@ @am__quote@CodeTools/$(DEPDIR)/ResolvProtoDump.Po@am__quote@
    11091176@AMDEP_TRUE@@am__include@ @am__quote@CodeTools/$(DEPDIR)/TrackLoc.Po@am__quote@
    11101177@AMDEP_TRUE@@am__include@ @am__quote@Common/$(DEPDIR)/Assert.Po@am__quote@
     
    11591226@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/PtrsCastable.Po@am__quote@
    11601227@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/RenameVars.Po@am__quote@
     1228@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/ResolveAssertions.Po@am__quote@
    11611229@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/ResolveTypeof.Po@am__quote@
    11621230@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/Resolver.Po@am__quote@
     1231@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/SpecCost.Po@am__quote@
    11631232@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/TypeEnvironment.Po@am__quote@
    11641233@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/Unify.Po@am__quote@
     
    12281297@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
    12291298
     1299.cc.lo:
     1300@am__fastdepCXX_TRUE@   $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
     1301@am__fastdepCXX_TRUE@   $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
     1302@am__fastdepCXX_TRUE@   $(am__mv) $$depbase.Tpo $$depbase.Plo
     1303@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
     1304@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1305@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
     1306
    12301307.ll.cc:
    12311308        $(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
     
    12331310.yy.cc:
    12341311        $(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h `echo $@ | $(am__yacc_c2h)` y.output $*.output -- $(YACCCOMPILE)
     1312
     1313mostlyclean-libtool:
     1314        -rm -f *.lo
     1315
     1316clean-libtool:
     1317        -rm -rf .libs _libs
     1318        -rm -rf ../driver/.libs ../driver/_libs
    12351319
    12361320ID: $(am__tagged_files)
     
    13921476clean: clean-am
    13931477
    1394 clean-am: clean-cfa_cpplibPROGRAMS clean-generic clean-noinstLIBRARIES \
    1395         mostlyclean-am
     1478clean-am: clean-cfa_cpplibPROGRAMS clean-generic clean-libtool \
     1479        clean-noinstLIBRARIES mostlyclean-am
    13961480
    13971481distclean: distclean-am
     
    14481532mostlyclean: mostlyclean-am
    14491533
    1450 mostlyclean-am: mostlyclean-compile mostlyclean-generic
     1534mostlyclean-am: mostlyclean-compile mostlyclean-generic \
     1535        mostlyclean-libtool
    14511536
    14521537pdf: pdf-am
     
    14631548
    14641549.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
    1465         clean-cfa_cpplibPROGRAMS clean-generic clean-noinstLIBRARIES \
    1466         cscopelist-am ctags ctags-am distclean distclean-compile \
    1467         distclean-generic distclean-tags distdir dvi dvi-am html \
    1468         html-am info info-am install install-am \
    1469         install-cfa_cpplibPROGRAMS install-data install-data-am \
    1470         install-dvi install-dvi-am install-exec install-exec-am \
    1471         install-html install-html-am install-info install-info-am \
    1472         install-man install-pdf install-pdf-am install-ps \
    1473         install-ps-am install-strip installcheck installcheck-am \
    1474         installdirs maintainer-clean maintainer-clean-generic \
    1475         mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \
    1476         ps ps-am tags tags-am uninstall uninstall-am \
     1550        clean-cfa_cpplibPROGRAMS clean-generic clean-libtool \
     1551        clean-noinstLIBRARIES cscopelist-am ctags ctags-am distclean \
     1552        distclean-compile distclean-generic distclean-libtool \
     1553        distclean-tags distdir dvi dvi-am html html-am info info-am \
     1554        install install-am install-cfa_cpplibPROGRAMS install-data \
     1555        install-data-am install-dvi install-dvi-am install-exec \
     1556        install-exec-am install-html install-html-am install-info \
     1557        install-info-am install-man install-pdf install-pdf-am \
     1558        install-ps install-ps-am install-strip installcheck \
     1559        installcheck-am installdirs maintainer-clean \
     1560        maintainer-clean-generic mostlyclean mostlyclean-compile \
     1561        mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
     1562        tags tags-am uninstall uninstall-am \
    14771563        uninstall-cfa_cpplibPROGRAMS
    14781564
  • src/Parser/DeclarationNode.cc

    r9b086ca rcde3891  
    1010// Created On       : Sat May 16 12:34:05 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul 20 14:56:54 2018
    13 // Update Count     : 1107
     12// Last Modified On : Thu Nov  1 20:54:26 2018
     13// Update Count     : 1108
    1414//
    1515
     
    402402}
    403403
    404 DeclarationNode * DeclarationNode::newTypeof( ExpressionNode * expr ) {
    405         DeclarationNode * newnode = new DeclarationNode;
    406         newnode->type = new TypeData( TypeData::Typeof );
     404DeclarationNode * DeclarationNode::newTypeof( ExpressionNode * expr, bool basetypeof ) {
     405        DeclarationNode * newnode = new DeclarationNode;
     406        newnode->type = new TypeData( basetypeof ? TypeData::Basetypeof : TypeData::Typeof );
    407407        newnode->type->typeexpr = expr;
    408408        return newnode;
  • src/Parser/LinkageSpec.cc

    r9b086ca rcde3891  
    1010// Created On       : Sat May 16 13:22:09 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jul  7 11:11:00 2017
    13 // Update Count     : 25
     12// Last Modified On : Thr Spt 12 15:59:00 2018
     13// Update Count     : 26
    1414//
    1515
     
    2323
    2424namespace LinkageSpec {
    25 
    26 Spec linkageCheck( CodeLocation location, const string * spec ) {
    27         assert( spec );
    28         unique_ptr<const string> guard( spec ); // allocated by lexer
    29         if ( *spec == "\"Cforall\"" ) {
    30                 return Cforall;
    31         } else if ( *spec == "\"C\"" ) {
    32                 return C;
    33         } else if ( *spec == "\"BuiltinC\"" ) {
    34                 return BuiltinC;
    35         } else {
    36                 SemanticError( location, "Invalid linkage specifier " + *spec );
    37         } // if
    38 }
    3925
    4026Spec linkageUpdate( CodeLocation location, Spec old_spec, const string * cmd ) {
  • src/Parser/LinkageSpec.h

    r9b086ca rcde3891  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Sat May 16 13:24:28 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jul  2 07:46:49 2018
    13 // Update Count     : 16
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thr Spt 13 15:59:00 2018
     13// Update Count     : 17
    1414//
    1515
     
    4141
    4242
    43         Spec linkageCheck( CodeLocation location, const std::string * );
    44         // Returns the Spec with the given name (limited to C, Cforall & BuiltinC)
    4543        Spec linkageUpdate( CodeLocation location, Spec old_spec, const std::string * cmd );
    4644        /* If cmd = "C" returns a Spec that is old_spec with is_mangled = false
  • src/Parser/ParseNode.h

    r9b086ca rcde3891  
    1010// Created On       : Sat May 16 13:28:16 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Aug  4 09:39:40 2018
    13 // Update Count     : 853
     12// Last Modified On : Thu Nov  1 20:54:53 2018
     13// Update Count     : 854
    1414//
    1515
     
    249249        static DeclarationNode * newBitfield( ExpressionNode * size );
    250250        static DeclarationNode * newTuple( DeclarationNode * members );
    251         static DeclarationNode * newTypeof( ExpressionNode * expr );
     251        static DeclarationNode * newTypeof( ExpressionNode * expr, bool basetypeof = false );
    252252        static DeclarationNode * newAttr( const std::string *, ExpressionNode * expr ); // @ attributes
    253253        static DeclarationNode * newAttr( const std::string *, DeclarationNode * type ); // @ attributes
  • src/Parser/TypeData.cc

    r9b086ca rcde3891  
    1010// Created On       : Sat May 16 15:12:51 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul 20 14:39:31 2018
    13 // Update Count     : 622
     12// Last Modified On : Fri Nov  2 07:54:26 2018
     13// Update Count     : 624
    1414//
    1515
     
    9696                break;
    9797          case Typeof:
     98          case Basetypeof:
    9899                // typeexpr = new Typeof_t;
    99100                typeexpr = nullptr;
     
    166167                break;
    167168          case Typeof:
     169          case Basetypeof:
    168170                // delete typeexpr->expr;
    169171                delete typeexpr;
     
    245247                break;
    246248          case Typeof:
     249          case Basetypeof:
    247250                newtype->typeexpr = maybeClone( typeexpr );
    248251                break;
     
    319322                        function.params->printList( os, indent + 4 );
    320323                } else {
    321                         os << string( indent + 2, ' ' ) << "with no parameters " << endl;
     324                        os << string( indent + 2, ' ' ) << "with no parameters" << endl;
    322325                } // if
    323326                if ( function.idList ) {
     
    344347                os << DeclarationNode::aggregateNames[ aggregate.kind ] << ' ' << *aggregate.name << endl;
    345348                if ( aggregate.params ) {
    346                         os << string( indent + 2, ' ' ) << "with type parameters " << endl;
     349                        os << string( indent + 2, ' ' ) << "with type parameters" << endl;
    347350                        aggregate.params->printList( os, indent + 4 );
    348351                } // if
    349352                if ( aggregate.actuals ) {
    350                         os << string( indent + 2, ' ' ) << "instantiated with actual parameters " << endl;
     353                        os << string( indent + 2, ' ' ) << "instantiated with actual parameters" << endl;
    351354                        aggregate.actuals->printList( os, indent + 4 );
    352355                } // if
    353356                if ( aggregate.fields ) {
    354                         os << string( indent + 2, ' ' ) << "with members " << endl;
     357                        os << string( indent + 2, ' ' ) << "with members" << endl;
    355358                        aggregate.fields->printList( os, indent + 4 );
    356359                } // if
    357360                if ( aggregate.body ) {
    358                         os << string( indent + 2, ' ' ) << " with body " << endl;
     361                        os << string( indent + 2, ' ' ) << " with body" << endl;
    359362                } // if
    360363                break;
     
    367370                } // if
    368371                if ( aggInst.params ) {
    369                         os << string( indent + 2, ' ' ) << "with parameters " << endl;
     372                        os << string( indent + 2, ' ' ) << "with parameters" << endl;
    370373                        aggInst.params->printList( os, indent + 2 );
    371374                } // if
     
    378381                } // if
    379382                if ( enumeration.body ) {
    380                         os << string( indent + 2, ' ' ) << " with body " << endl;
     383                        os << string( indent + 2, ' ' ) << " with body" << endl;
    381384                } // if
    382385                break;
     
    415418                os << "tuple ";
    416419                if ( tuple ) {
    417                         os << "with members " << endl;
     420                        os << "with members" << endl;
    418421                        tuple->printList( os, indent + 2 );
    419422                } // if
    420423                break;
     424          case Basetypeof:
     425                os << "base-";
     426                #if defined(__GNUC__) && __GNUC__ >= 7
     427                        __attribute__((fallthrough));
     428                #endif
    421429          case Typeof:
    422430                os << "type-of expression ";
     
    457465          case Tuple:
    458466          case Typeof:
     467          case Basetypeof:
    459468          case Builtin:
    460469                assertf(false, "Tried to get leaf name from kind without a name: %d", kind);
     
    513522        switch ( td->kind ) {
    514523          case TypeData::Unknown:
    515                 // fill in implicit int
    516                 return new BasicType( buildQualifiers( td ), BasicType::SignedInt );
     524                        // fill in implicit int
     525                        return new BasicType( buildQualifiers( td ), BasicType::SignedInt );
    517526          case TypeData::Basic:
    518                 return buildBasicType( td );
     527                        return buildBasicType( td );
    519528          case TypeData::Pointer:
    520                 return buildPointer( td );
     529                        return buildPointer( td );
    521530          case TypeData::Array:
    522                 return buildArray( td );
     531                        return buildArray( td );
    523532          case TypeData::Reference:
    524                 return buildReference( td );
     533                        return buildReference( td );
    525534          case TypeData::Function:
    526                 return buildFunction( td );
     535                        return buildFunction( td );
    527536          case TypeData::AggregateInst:
    528                 return buildAggInst( td );
     537                        return buildAggInst( td );
    529538          case TypeData::EnumConstant:
    530                 // the name gets filled in later -- by SymTab::Validate
    531                 return new EnumInstType( buildQualifiers( td ), "" );
     539                        // the name gets filled in later -- by SymTab::Validate
     540                        return new EnumInstType( buildQualifiers( td ), "" );
    532541          case TypeData::SymbolicInst:
    533                 return buildSymbolicInst( td );
     542                        return buildSymbolicInst( td );
    534543          case TypeData::Tuple:
    535                 return buildTuple( td );
     544                        return buildTuple( td );
    536545          case TypeData::Typeof:
    537                 return buildTypeof( td );
     546          case TypeData::Basetypeof:
     547                        return buildTypeof( td );
    538548          case TypeData::Builtin:
    539                 if(td->builtintype == DeclarationNode::Zero) {
    540                         return new ZeroType( noQualifiers );
    541                 }
    542                 else if(td->builtintype == DeclarationNode::One) {
    543                         return new OneType( noQualifiers );
    544                 }
    545                 else {
    546                         return new VarArgsType( buildQualifiers( td ) );
    547                 }
     549                        if (td->builtintype == DeclarationNode::Zero) {
     550                                return new ZeroType( noQualifiers );
     551                        }
     552                        else if (td->builtintype == DeclarationNode::One) {
     553                                return new OneType( noQualifiers );
     554                        }
     555                        else {
     556                                return new VarArgsType( buildQualifiers( td ) );
     557                        }
    548558          case TypeData::GlobalScope:
    549                 return new GlobalScopeType();
     559                        return new GlobalScopeType();
    550560                case TypeData::Qualified:
    551                 return new QualifiedType( buildQualifiers( td ), typebuild( td->qualified.parent ), typebuild( td->qualified.child ) );
     561                        return new QualifiedType( buildQualifiers( td ), typebuild( td->qualified.parent ), typebuild( td->qualified.child ) );
    552562          case TypeData::Symbolic:
    553563          case TypeData::Enum:
    554564          case TypeData::Aggregate:
    555                 assert( false );
     565                        assert( false );
    556566        } // switch
    557567
     
    929939
    930940TypeofType * buildTypeof( const TypeData * td ) {
    931         assert( td->kind == TypeData::Typeof );
     941        assert( td->kind == TypeData::Typeof || td->kind == TypeData::Basetypeof );
    932942        assert( td->typeexpr );
    933943        // assert( td->typeexpr->expr );
    934         return new TypeofType( buildQualifiers( td ), td->typeexpr->build() );
     944        return new TypeofType{
     945                buildQualifiers( td ), td->typeexpr->build(), td->kind == TypeData::Basetypeof };
    935946} // buildTypeof
    936947
  • src/Parser/TypeData.h

    r9b086ca rcde3891  
    1010// Created On       : Sat May 16 15:18:36 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul 20 13:56:40 2018
    13 // Update Count     : 195
     12// Last Modified On : Thu Nov  1 20:56:46 2018
     13// Update Count     : 196
    1414//
    1515
     
    2727struct TypeData {
    2828        enum Kind { Basic, Pointer, Reference, Array, Function, Aggregate, AggregateInst, Enum, EnumConstant, Symbolic,
    29                                 SymbolicInst, Tuple, Typeof, Builtin, GlobalScope, Qualified, Unknown };
     29                                SymbolicInst, Tuple, Typeof, Basetypeof, Builtin, GlobalScope, Qualified, Unknown };
    3030
    3131        struct Aggregate_t {
  • src/Parser/lex.ll

    r9b086ca rcde3891  
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Wed Aug  8 17:23:17 2018
    13  * Update Count     : 685
     12 * Last Modified On : Thu Nov  1 20:57:35 2018
     13 * Update Count     : 687
    1414 */
    1515
     
    209209__attribute__   { KEYWORD_RETURN(ATTRIBUTE); }                  // GCC
    210210auto                    { KEYWORD_RETURN(AUTO); }
     211basetypeof              { KEYWORD_RETURN(BASETYPEOF); }                 // CFA
    211212_Bool                   { KEYWORD_RETURN(BOOL); }                               // C99
    212213break                   { KEYWORD_RETURN(BREAK); }
     
    410411">>="                   { NAMEDOP_RETURN(RSassign); }
    411412
    412 "~="                    { NAMEDOP_RETURN(Erange); }                             // CFA
    413413"@="                    { NAMEDOP_RETURN(ATassign); }                   // CFA
     414"~="                    { NAMEDOP_RETURN(ErangeUpEq); }                 // CFA
     415"-~"                    { NAMEDOP_RETURN(ErangeDown); }                 // CFA
     416"-~="                   { NAMEDOP_RETURN(ErangeDownEq); }               // CFA
    414417
    415418                                /* CFA, operator identifier */
  • src/Parser/parser.yy

    r9b086ca rcde3891  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Aug  8 17:50:07 2018
    13 // Update Count     : 3998
     12// Last Modified On : Thu Nov  8 18:08:23 2018
     13// Update Count     : 4052
    1414//
    1515
     
    187187
    188188ForCtrl * forCtrl( ExpressionNode * type, string * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
     189        ConstantExpr * constant = dynamic_cast<ConstantExpr *>(type->get_expr());
     190        if ( constant && (constant->get_constant()->get_value() == "0" || constant->get_constant()->get_value() == "1") ) {
     191        type = new ExpressionNode( new CastExpr( maybeMoveBuild< Expression >(type), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ) );
     192        } // if
    189193        return new ForCtrl(
    190                 distAttr( DeclarationNode::newTypeof( type ), DeclarationNode::newName( index )->addInitializer( new InitializerNode( start ) ) ),
     194                distAttr( DeclarationNode::newTypeof( type, true ), DeclarationNode::newName( index )->addInitializer( new InitializerNode( start ) ) ),
    191195                new ExpressionNode( build_binary_val( compop, new ExpressionNode( build_varref( new string( *index ) ) ), comp ) ),
    192                 new ExpressionNode( build_binary_val( OperKinds::PlusAssn, new ExpressionNode( build_varref( new string( *index ) ) ), inc ) ) );
     196                new ExpressionNode( build_binary_val( compop == OperKinds::LThan || compop == OperKinds::LEThan ? // choose += or -= for upto/downto
     197                                                                                          OperKinds::PlusAssn : OperKinds::MinusAssn, new ExpressionNode( build_varref( new string( *index ) ) ), inc ) ) );
     198} // forCtrl
     199
     200ForCtrl * forCtrl( ExpressionNode * type, ExpressionNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
     201        if ( NameExpr * identifier = dynamic_cast<NameExpr *>(index->get_expr()) ) {
     202                return forCtrl( type, new string( identifier->name ), start, compop, comp, inc );
     203        } else {
     204                SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed" ); return nullptr;
     205        } // if
    193206} // forCtrl
    194207
     
    214227
    215228// Types declaration for productions
    216 %union
    217 {
     229%union {
    218230        Token tok;
    219231        ParseNode * pn;
     
    254266%token ZERO_T ONE_T                                                                             // CFA
    255267%token VALIST                                                                                   // GCC
    256 %token TYPEOF LABEL                                                                             // GCC
     268%token TYPEOF BASETYPEOF LABEL                                                  // GCC
    257269%token ENUM STRUCT UNION
    258270%token EXCEPTION                                                                                // CFA
     
    290302%token ANDassign        ERassign        ORassign                                // &=   ^=      |=
    291303
    292 %token Erange                                                                                   // ~=
     304%token ErangeUpEq       ErangeDown      ErangeDownEq                    // ~=   -~      -~=
    293305%token ATassign                                                                                 // @=
    294306
     
    629641                { $$ = new ExpressionNode( build_fieldSel( $1, build_tuple( $4 ) ) ); }
    630642        | postfix_expression ARROW no_attr_identifier
    631                 {
    632                         $$ = new ExpressionNode( build_pfieldSel( $1, *$3 == "0" || *$3 == "1" ? build_constantInteger( *$3 ) : build_varref( $3 ) ) );
    633                 }
     643                { $$ = new ExpressionNode( build_pfieldSel( $1, build_varref( $3 ) ) ); }
    634644        | postfix_expression ARROW INTEGERconstant                      // CFA, tuple index
    635645                { $$ = new ExpressionNode( build_pfieldSel( $1, build_constantInteger( *$3 ) ) ); }
     
    11301140        | FOR '(' push for_control_expression ')' statement pop
    11311141                { $$ = new StatementNode( build_for( $4, $6 ) ); }
     1142        | FOR '(' ')' statement                                                         // CFA => for ( ;; )
     1143                { $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), $4 ) ); }
    11321144        ;
    11331145
    11341146for_control_expression:
    1135         comma_expression_opt                                                            // CFA
    1136                 {
    1137                         if ( ! $1 ) {                                                           // => for ( ;; )
    1138                                 $$ = new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr );
    1139                         } else {
    1140                                 $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), new ExpressionNode( build_constantInteger( *new string( "0" ) ) ), OperKinds::LThan, $1->clone(),
    1141                                                          new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) );
    1142                         } // if
    1143                 }
     1147        comma_expression                                                                        // CFA
     1148                { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), new ExpressionNode( build_constantInteger( *new string( "0" ) ) ),
     1149                                                OperKinds::LThan, $1->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
    11441150        | constant_expression inclexcl constant_expression      // CFA
    11451151                { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), $1->clone(), $2, $3, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
    11461152        | constant_expression inclexcl constant_expression '~' constant_expression // CFA
    11471153                { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), $1->clone(), $2, $3, $5 ); }
    1148         | comma_expression_opt ';' comma_expression                     // CFA
    1149                 {
    1150                         if ( ! $1 ) {
    1151                                 SemanticError( yylloc, "Missing loop index." ); $$ = nullptr;
    1152                         } else if ( ! $3 ) {
    1153                                 SemanticError( yylloc, "Missing loop range." ); $$ = nullptr;
    1154                         } else {
    1155                                 if ( NameExpr *identifier = dynamic_cast<NameExpr *>($1->get_expr()) ) {
    1156                                         $$ = forCtrl( $3, new string( identifier->name ), new ExpressionNode( build_constantInteger( *new string( "0" ) ) ), OperKinds::LThan, $3->clone(),
    1157                                                                  new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) );
    1158                                 } else {
    1159                                         SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed" ); $$ = nullptr;
    1160                                 } // if
    1161                         } // if
    1162                 }
    1163         | comma_expression_opt ';' constant_expression inclexcl constant_expression // CFA
    1164                 {
    1165                         if ( ! $1 ) {
    1166                                 SemanticError( yylloc, "Missing loop index." ); $$ = nullptr;
    1167                         } else {
    1168                                 if ( NameExpr *identifier = dynamic_cast<NameExpr *>($1->get_expr()) ) {
    1169                                         $$ = forCtrl( $3, new string( identifier->name ), $3->clone(), $4, $5, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) );
    1170                                 } else {
    1171                                         SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed" ); $$ = nullptr;
    1172                                 } // if
    1173                         } // if
    1174                 }
    1175         | comma_expression_opt ';' constant_expression inclexcl constant_expression '~' constant_expression // CFA
    1176                 {
    1177                         if ( ! $1 ) {
    1178                                 SemanticError( yylloc, "Missing loop index." ); $$ = nullptr;
    1179                         } else {
    1180                                 if ( NameExpr *identifier = dynamic_cast<NameExpr *>($1->get_expr()) ) {
    1181                                         $$ = forCtrl( $3, new string( identifier->name ), $3->clone(), $4, $5, $7 );
    1182                                 } else {
    1183                                         SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed" ); $$ = nullptr;
    1184                                 } // if
    1185                         } // if
    1186                 }
    1187         | comma_expression_opt ';' comma_expression_opt ';' comma_expression_opt
     1154        | comma_expression ';' comma_expression                         // CFA
     1155                { $$ = forCtrl( $3, $1, new ExpressionNode( build_constantInteger( *new string( "0" ) ) ),
     1156                                                OperKinds::LThan, $3->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
     1157        | comma_expression ';' constant_expression inclexcl constant_expression // CFA
     1158                { $$ = forCtrl( $3, $1, $3->clone(), $4, $5, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
     1159        | comma_expression ';' constant_expression inclexcl constant_expression '~' constant_expression // CFA
     1160                { $$ = forCtrl( $3, $1, $3->clone(), $4, $5, $7 ); }
     1161        | comma_expression ';' comma_expression_opt ';' comma_expression_opt
    11881162                { $$ = new ForCtrl( $1, $3, $5 ); }
     1163        | ';' comma_expression_opt ';' comma_expression_opt
     1164                { $$ = new ForCtrl( (ExpressionNode * )nullptr, $2, $4 ); }
    11891165        | declaration comma_expression_opt ';' comma_expression_opt // C99, declaration has ';'
    11901166                { $$ = new ForCtrl( $1, $2, $4 ); }
     
    11941170        '~'
    11951171                { $$ = OperKinds::LThan; }
    1196         | Erange
     1172        | ErangeUpEq
    11971173                { $$ = OperKinds::LEThan; }
     1174        | ErangeDown
     1175                { $$ = OperKinds::GThan; }
     1176        | ErangeDownEq
     1177                { $$ = OperKinds::GEThan; }
    11981178        ;
    11991179
     
    18441824
    18451825indirect_type:
    1846         TYPEOF '(' type ')'                                                                     // GCC: typeof(x) y;
     1826        TYPEOF '(' type ')'                                                                     // GCC: typeof( x ) y;
    18471827                { $$ = $3; }
    1848         | TYPEOF '(' comma_expression ')'                                       // GCC: typeof(a+b) y;
     1828        | TYPEOF '(' comma_expression ')'                                       // GCC: typeof( a+b ) y;
    18491829                { $$ = DeclarationNode::newTypeof( $3 ); }
    1850         | ATTR_TYPEGENname '(' type ')'                                         // CFA: e.g., @type(x) y;
     1830        | BASETYPEOF '(' type ')'                                                       // CFA: basetypeof( x ) y;
     1831                { $$ = DeclarationNode::newTypeof( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ), true ); }
     1832        | BASETYPEOF '(' comma_expression ')'                           // CFA: basetypeof( a+b ) y;
     1833                { $$ = DeclarationNode::newTypeof( $3, true ); }
     1834        | ATTR_TYPEGENname '(' type ')'                                         // CFA: e.g., @type( x ) y;
    18511835                { $$ = DeclarationNode::newAttr( $1, $3 ); }
    1852         | ATTR_TYPEGENname '(' comma_expression ')'                     // CFA: e.g., @type(a+b) y;
     1836        | ATTR_TYPEGENname '(' comma_expression ')'                     // CFA: e.g., @type( a+b ) y;
    18531837                { $$ = DeclarationNode::newAttr( $1, $3 ); }
    18541838        | ZERO_T                                                                                        // CFA
  • src/ResolvExpr/Alternative.cc

    r9b086ca rcde3891  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sat May 16 23:44:23 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat May 16 23:54:23 2015
    13 // Update Count     : 2
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Thu Oct 11 10:55:00 2018
     13// Update Count     : 3
    1414//
    1515
     
    2020#include <utility>                       // for move
    2121
    22 #include "Common/utility.h"              // for maybeClone
     22#include "Common/utility.h"              // for cloneAll
    2323#include "ResolvExpr/Cost.h"             // for Cost, Cost::zero, operator<<
    2424#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
     
    2727
    2828namespace ResolvExpr {
    29         Alternative::Alternative() : cost( Cost::zero ), cvtCost( Cost::zero ), expr( nullptr ) {}
     29        Alternative::Alternative()
     30        : cost( Cost::zero ), cvtCost( Cost::zero ), expr( nullptr ), env(), openVars(), need() {}
    3031
    31         Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost )
    32                 : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ) {}
     32        Alternative::Alternative( Expression *expr, const TypeEnvironment &env )
     33        : cost( Cost::zero ), cvtCost( Cost::zero ), expr( expr ), env( env ), openVars(), need() {}
     34       
     35        Alternative::Alternative( const Alternative &o, Expression *expr, const Cost &cost )
     36        : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( o.env ), openVars( o.openVars ),
     37          need() { cloneAll( o.need, need ); }
    3338
    34         Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost, const Cost &cvtCost )
    35                 : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ) {}
     39        Alternative::Alternative( Expression *expr, const TypeEnvironment &env,
     40                const OpenVarSet& openVars, const AssertionList& oneed, const Cost& cost )
     41        : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ), openVars( openVars ),
     42          need() { cloneAll( oneed, need ); }
    3643
    37         Alternative::Alternative( const Alternative &other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ), env( other.env ) {
    38         }
     44        Alternative::Alternative( Expression *expr, const TypeEnvironment &env,
     45                const OpenVarSet& openVars, const AssertionList& oneed, const Cost& cost,
     46                const Cost &cvtCost )
     47        : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ), openVars( openVars ),
     48          need() { cloneAll( oneed, need ); }
     49       
     50        Alternative::Alternative( Expression *expr, const TypeEnvironment &env,
     51                const OpenVarSet &openVars, const AssertionSet &oneed, const Cost &cost)
     52        : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ), openVars( openVars ),
     53          need() { cloneAll( oneed, need ); }
     54       
     55        Alternative::Alternative( Expression *expr, const TypeEnvironment &env,
     56                const OpenVarSet &openVars, const AssertionSet &oneed, const Cost &cost,
     57                const Cost& cvtCost )
     58        : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ), openVars( openVars ),
     59          need() { cloneAll( oneed, need ); }
     60       
     61        Alternative::Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars,
     62                AssertionSet &&needSet, const Cost &cost )
     63        : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( std::move(env) ),
     64          openVars( std::move(openVars) ), need( needSet.begin(), needSet.end() ) {}
     65       
     66        Alternative::Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars,
     67                AssertionSet &&needSet, const Cost &cost, const Cost &cvtCost )
     68        : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( std::move(env) ),
     69          openVars( std::move(openVars) ), need( needSet.begin(), needSet.end() ) {}
     70
     71        Alternative::Alternative( const Alternative &other )
     72        : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ),
     73          env( other.env ), openVars( other.openVars ), need() { cloneAll( other.need, need ); }
    3974
    4075        Alternative &Alternative::operator=( const Alternative &other ) {
     
    4580                expr = maybeClone( other.expr );
    4681                env = other.env;
     82                openVars = other.openVars;
     83                need.clear();
     84                cloneAll( other.need, need );
    4785                return *this;
    4886        }
    4987
    50         Alternative::Alternative( Alternative && other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( other.expr ), env( std::move( other.env ) ) {
    51                 other.expr = nullptr;
    52         }
     88        Alternative::Alternative( Alternative && other )
     89        : cost( other.cost ), cvtCost( other.cvtCost ), expr( other.expr ),
     90          env( std::move( other.env ) ), openVars( std::move( other.openVars ) ),
     91          need( std::move( other.need ) ) { other.expr = nullptr; }
    5392
    5493        Alternative & Alternative::operator=( Alternative && other ) {
     
    5998                expr = other.expr;
    6099                env = std::move( other.env );
     100                openVars = std::move( other.openVars );
     101                need = std::move( other.need );
    61102                other.expr = nullptr;
    62103                return *this;
     
    64105
    65106        Alternative::~Alternative() {
     107                for ( AssertionItem& n : need ) { delete n.decl; }
    66108                delete expr;
    67109        }
     
    78120                        os << "Null expression!" << std::endl;
    79121                } // if
    80                 os << indent << "Environment: ";
     122                os << indent << "Environment:";
    81123                env.print( os, indent+1 );
    82124                os << std::endl;
  • src/ResolvExpr/Alternative.h

    r9b086ca rcde3891  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sat May 16 23:45:43 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:36:36 2017
    13 // Update Count     : 3
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Thu Oct 11 10:55:00 2018
     13// Update Count     : 4
    1414//
    1515
     
    2020
    2121#include "Cost.h"             // for Cost
    22 #include "TypeEnvironment.h"  // for TypeEnvironment
     22#include "TypeEnvironment.h"  // for TypeEnvironment, AssertionSetValue
     23
     24#include "Common/utility.h"   // for maybeClone
    2325
    2426class Expression;
    2527
    2628namespace ResolvExpr {
     29        /// One assertion to resolve
     30        struct AssertionItem {
     31                DeclarationWithType* decl;
     32                AssertionSetValue info;
     33               
     34                AssertionItem() = default;
     35                AssertionItem( DeclarationWithType* decl, const AssertionSetValue& info )
     36                : decl(decl), info(info) {}
     37                AssertionItem( const AssertionSet::value_type& e ) : decl(e.first), info(e.second) {}
     38                operator AssertionSet::value_type () const { return { decl, info }; }
     39
     40                // to support cloneAll
     41                AssertionItem clone() const { return { maybeClone(decl), info }; }
     42        };
     43        /// A list of unresolved assertions
     44        using AssertionList = std::vector<AssertionItem>;
     45
     46        /// Clones an assertion list into an assertion set
     47        static inline void cloneAll( const AssertionList& src, AssertionSet& dst ) {
     48                for ( const AssertionItem& item : src ) {
     49                        dst.emplace( maybeClone(item.decl), item.info );
     50                }
     51        }
     52
     53        /// Clones an assertion set into an assertion list
     54        static inline void cloneAll( const AssertionSet& src, AssertionList& dst ) {
     55                dst.reserve( dst.size() + src.size() );
     56                for ( const auto& entry : src ) {
     57                        dst.emplace_back( maybeClone(entry.first), entry.second );
     58                }
     59        }
     60
     61        /// Clones an assertion list into an assertion list
     62        static inline void cloneAll( const AssertionList& src, AssertionList& dst ) {
     63                dst.reserve( dst.size() + src.size() );
     64                for ( const AssertionItem& item : src ) {
     65                        dst.emplace_back( maybeClone(item.decl), item.info );
     66                }
     67        }
     68
     69        /// One option for resolution of an expression
    2770        struct Alternative {
    2871                Alternative();
    29                 Alternative( Expression *expr, const TypeEnvironment &env, const Cost &cost );
    30                 Alternative( Expression *expr, const TypeEnvironment &env, const Cost &cost, const Cost &cvtCost );
     72                Alternative( Expression *expr, const TypeEnvironment &env );
     73                Alternative( const Alternative &o, Expression *expr, const Cost &cost );
     74                Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet& openVars,
     75                        const AssertionList& need, const Cost &cost );
     76                Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet& openVars,
     77                        const AssertionList& need, const Cost &cost, const Cost &cvtCost );
     78                Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet &openVars,
     79                        const AssertionSet &need, const Cost &cost);
     80                Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet &openVars,
     81                        const AssertionSet &need, const Cost &cost, const Cost& cvtCost );
     82                Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars,
     83                        AssertionSet &&need, const Cost &cost );
     84                Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars,
     85                        AssertionSet &&need, const Cost &cost, const Cost &cvtCost );
    3186                Alternative( const Alternative &other );
    3287                Alternative &operator=( const Alternative &other );
     
    4499                }
    45100
    46                 Cost cost;
    47                 Cost cvtCost;
    48                 Expression *expr;
    49                 TypeEnvironment env;
     101                /// Sorts by cost
     102                bool operator< ( const Alternative& o ) const { return cost < o.cost; }
     103
     104                Cost cost;            ///< Cost of the whole expression
     105                Cost cvtCost;         ///< Cost of conversions to the satisfying expression
     106                Expression *expr;     ///< Satisfying expression
     107                TypeEnvironment env;  ///< Containing type environment
     108                OpenVarSet openVars;  ///< Open variables for environment
     109                AssertionList need;   ///< Assertions which need to be resolved
    50110        };
    51111
  • src/ResolvExpr/AlternativeFinder.cc

    r9b086ca rcde3891  
    1010// Created On       : Sat May 16 23:52:08 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Feb 17 11:19:39 2018
    13 // Update Count     : 33
     12// Last Modified On : Thu Nov  1 21:00:56 2018
     13// Update Count     : 35
    1414//
    1515
     
    3434#include "InitTweak/InitTweak.h"   // for getFunctionName
    3535#include "RenameVars.h"            // for RenameVars, global_renamer
     36#include "ResolveAssertions.h"     // for resolveAssertions
    3637#include "ResolveTypeof.h"         // for resolveTypeof
    3738#include "Resolver.h"              // for resolveStmtExpr
     
    102103                void addAnonConversions( const Alternative & alt );
    103104                /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member
    104                 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name );
     105                template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative &alt, const Cost &newCost, const std::string & name );
    105106                /// Adds alternatives for member expressions where the left side has tuple type
    106                 void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member );
     107                void addTupleMembers( TupleType *tupleType, Expression *expr, const Alternative &alt, const Cost &newCost, Expression *member );
    107108                /// Adds alternatives for offsetof expressions, given the base type and name of the member
    108109                template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name );
     
    113114                template<typename OutputIterator>
    114115                void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out );
    115                 /// Checks if assertion parameters match for a new alternative
     116                /// Sets up parameter inference for an output alternative
    116117                template< typename OutputIterator >
    117                 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out );
     118                void inferParameters( Alternative &newAlt, OutputIterator out );
    118119        private:
    119120                AlternativeFinder & altFinder;
     
    244245        }
    245246
    246         void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast ) {
     247        void AlternativeFinder::find( Expression *expr, ResolvMode mode ) {
    247248                PassVisitor<Finder> finder( *this );
    248249                expr->accept( finder );
    249                 if ( failFast && alternatives.empty() ) {
     250                if ( mode.failFast && alternatives.empty() ) {
    250251                        PRINT(
    251252                                std::cerr << "No reasonable alternatives for expression " << expr << std::endl;
     
    253254                        SemanticError( expr, "No reasonable alternatives for expression " );
    254255                }
    255                 if ( prune ) {
     256                if ( mode.resolveAssns || mode.prune ) {
     257                        // trim candidates just to those where the assertions resolve
     258                        // - necessary pre-requisite to pruning
     259                        AltList candidates;
     260                        for ( unsigned i = 0; i < alternatives.size(); ++i ) {
     261                                resolveAssertions( alternatives[i], indexer, candidates );
     262                        }
     263                        // fail early if none such
     264                        if ( mode.failFast && candidates.empty() ) {
     265                                std::ostringstream stream;
     266                                stream << "No resolvable alternatives for expression " << expr << "\n"
     267                                       << "Alternatives with failing assertions are:\n";
     268                                printAlts( alternatives, stream, 1 );
     269                                SemanticError( expr->location, stream.str() );
     270                        }
     271                        // reset alternatives
     272                        alternatives = std::move( candidates );
     273                }
     274                if ( mode.prune ) {
    256275                        auto oldsize = alternatives.size();
    257276                        PRINT(
     
    261280                        AltList pruned;
    262281                        pruneAlternatives( alternatives.begin(), alternatives.end(), back_inserter( pruned ) );
    263                         if ( failFast && pruned.empty() ) {
     282                        if ( mode.failFast && pruned.empty() ) {
    264283                                std::ostringstream stream;
    265284                                AltList winners;
     
    280299                }
    281300                // adjust types after pruning so that types substituted by pruneAlternatives are correctly adjusted
    282                 for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i ) {
    283                         if ( adjust ) {
    284                                 adjustExprType( i->expr->get_result(), i->env, indexer );
     301                if ( mode.adjust ) {
     302                        for ( Alternative& i : alternatives ) {
     303                                adjustExprType( i.expr->get_result(), i.env, indexer );
    285304                        }
    286305                }
     
    294313
    295314        void AlternativeFinder::findWithAdjustment( Expression *expr ) {
    296                 find( expr, true );
     315                find( expr, ResolvMode::withAdjustment() );
    297316        }
    298317
    299318        void AlternativeFinder::findWithoutPrune( Expression * expr ) {
    300                 find( expr, true, false );
     319                find( expr, ResolvMode::withoutPrune() );
    301320        }
    302321
    303322        void AlternativeFinder::maybeFind( Expression * expr ) {
    304                 find( expr, true, true, false );
     323                find( expr, ResolvMode::withoutFailFast() );
    305324        }
    306325
     
    317336
    318337                if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) {
    319                         addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" );
     338                        addAggMembers( structInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" );
    320339                } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) {
    321                         addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" );
     340                        addAggMembers( unionInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" );
    322341                } // if
    323342        }
    324343
    325344        template< typename StructOrUnionType >
    326         void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name ) {
     345        void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative& alt, const Cost &newCost, const std::string & name ) {
    327346                std::list< Declaration* > members;
    328347                aggInst->lookup( name, members );
     
    332351                                // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
    333352                                // can't construct in place and use vector::back
    334                                 Alternative newAlt( new MemberExpr( dwt, expr->clone() ), env, newCost );
     353                                Alternative newAlt{ alt, new MemberExpr{ dwt, expr->clone() }, newCost };
    335354                                renameTypes( newAlt.expr );
    336355                                addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression.
     
    342361        }
    343362
    344         void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
     363        void AlternativeFinder::Finder::addTupleMembers( TupleType *tupleType, Expression *expr,                        const Alternative &alt, const Cost &newCost, Expression *member ) {
    345364                if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) {
    346365                        // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning
     
    348367                        std::string tmp;
    349368                        if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
    350                                 alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
     369                                alternatives.push_back( Alternative{
     370                                        alt, new TupleIndexExpr( expr->clone(), val ), newCost } );
    351371                        } // if
    352372                } // if
     
    354374
    355375        void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) {
    356                 alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) );
     376                alternatives.push_back( Alternative{ applicationExpr->clone(), env } );
    357377        }
    358378
     
    410430        Cost computeApplicationConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) {
    411431                ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( alt.expr );
    412                 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
    413                 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->get_base() );
     432                PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->function->result );
     433                FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->base );
    414434
    415435                Cost convCost = Cost::zero;
    416                 std::list< DeclarationWithType* >& formals = function->get_parameters();
     436                std::list< DeclarationWithType* >& formals = function->parameters;
    417437                std::list< DeclarationWithType* >::iterator formal = formals.begin();
    418                 std::list< Expression* >& actuals = appExpr->get_args();
    419 
    420                 for ( std::list< Expression* >::iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
    421                         Type * actualType = (*actualExpr)->get_result();
     438                std::list< Expression* >& actuals = appExpr->args;
     439
     440                for ( Expression*& actualExpr : actuals ) {
     441                        Type * actualType = actualExpr->result;
    422442                        PRINT(
    423443                                std::cerr << "actual expression:" << std::endl;
    424                                 (*actualExpr)->print( std::cerr, 8 );
     444                                actualExpr->print( std::cerr, 8 );
    425445                                std::cerr << "--- results are" << std::endl;
    426446                                actualType->print( std::cerr, 8 );
    427447                        )
    428448                        if ( formal == formals.end() ) {
    429                                 if ( function->get_isVarArgs() ) {
     449                                if ( function->isVarArgs ) {
    430450                                        convCost.incUnsafe();
    431451                                        PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; )
    432452                                        // convert reference-typed expressions to value-typed expressions
    433                                         referenceToRvalueConversion( *actualExpr, convCost );
     453                                        referenceToRvalueConversion( actualExpr, convCost );
    434454                                        continue;
    435455                                } else {
     
    437457                                }
    438458                        }
    439                         if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( *actualExpr ) ) {
     459                        if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( actualExpr ) ) {
    440460                                // default arguments should be free - don't include conversion cost.
    441461                                // Unwrap them here because they are not relevant to the rest of the system.
    442                                 *actualExpr = def->expr;
     462                                actualExpr = def->expr;
    443463                                ++formal;
    444464                                continue;
    445465                        }
     466                        // mark conversion cost to formal and also specialization cost of formal type
    446467                        Type * formalType = (*formal)->get_type();
    447                         convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env );
     468                        convCost += computeExpressionConversionCost( actualExpr, formalType, indexer, alt.env );
     469                        convCost.decSpec( specCost( formalType ) );
    448470                        ++formal; // can't be in for-loop update because of the continue
    449471                }
     
    452474                }
    453475
    454                 for ( InferredParams::const_iterator assert = appExpr->get_inferParams().begin(); assert != appExpr->get_inferParams().end(); ++assert ) {
    455                         convCost += computeConversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env );
     476                // specialization cost of return types can't be accounted for directly, it disables
     477                // otherwise-identical calls, like this example based on auto-newline in the I/O lib:
     478                //
     479                //   forall(otype OS) {
     480                //     void ?|?(OS&, int);  // with newline
     481                //     OS&  ?|?(OS&, int);  // no newline, always chosen due to more specialization
     482                //   }
     483
     484                // mark type variable and specialization cost of forall clause
     485                convCost.incVar( function->forall.size() );
     486                for ( TypeDecl* td : function->forall ) {
     487                        convCost.decSpec( td->assertions.size() );
    456488                }
    457489
     
    466498                                needAssertions[ *assert ].isUsed = true;
    467499                        }
    468 ///     needAssertions.insert( needAssertions.end(), (*tyvar)->get_assertions().begin(), (*tyvar)->get_assertions().end() );
    469                 }
    470         }
    471 
    472         static const int recursionLimit = /*10*/ 4;  ///< Limit to depth of recursion satisfaction
    473 
    474         void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) {
    475                 for ( AssertionSet::iterator i = assertSet.begin(); i != assertSet.end(); ++i ) {
    476                         if ( i->second.isUsed ) {
    477                                 indexer.addId( i->first );
    478                         }
    479                 }
    480         }
    481 
    482         template< typename ForwardIterator, typename OutputIterator >
    483         void inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, int level, const SymTab::Indexer &indexer, OutputIterator out ) {
    484                 if ( newAlt.cost == Cost::infinity ) return; // don't proceed down this dead end
    485                 if ( begin == end ) {
    486                         if ( newNeed.empty() ) {
    487                                 PRINT(
    488                                         std::cerr << "all assertions satisfied, output alternative: ";
    489                                         newAlt.print( std::cerr );
    490                                         std::cerr << std::endl;
    491                                 );
    492                                 *out++ = newAlt;
    493                                 return;
    494                         } else if ( level >= recursionLimit ) {
    495                                 SemanticError( newAlt.expr->location, "Too many recursive assertions" );
    496                         } else {
    497                                 AssertionSet newerNeed;
    498                                 PRINT(
    499                                         std::cerr << "recursing with new set:" << std::endl;
    500                                         printAssertionSet( newNeed, std::cerr, 8 );
    501                                 )
    502                                 inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, level+1, indexer, out );
    503                                 return;
    504                         }
    505                 }
    506 
    507                 ForwardIterator cur = begin++;
    508                 if ( ! cur->second.isUsed ) {
    509                         inferRecursive( begin, end, newAlt, openVars, decls, newNeed, level, indexer, out );
    510                         return; // xxx - should this continue? previously this wasn't here, and it looks like it should be
    511                 }
    512                 DeclarationWithType *curDecl = cur->first;
    513 
    514                 PRINT(
    515                         std::cerr << "inferRecursive: assertion is ";
    516                         curDecl->print( std::cerr );
    517                         std::cerr << std::endl;
    518                 )
    519                 std::list< SymTab::Indexer::IdData > candidates;
    520                 decls.lookupId( curDecl->get_name(), candidates );
    521 ///   if ( candidates.empty() ) { std::cerr << "no candidates!" << std::endl; }
    522                 for ( const auto & data : candidates ) {
    523                         DeclarationWithType * candidate = data.id;
    524                         PRINT(
    525                                 std::cerr << "inferRecursive: candidate is ";
    526                                 candidate->print( std::cerr );
    527                                 std::cerr << std::endl;
    528                         )
    529 
    530                         AssertionSet newHave, newerNeed( newNeed );
    531                         TypeEnvironment newEnv( newAlt.env );
    532                         OpenVarSet newOpenVars( openVars );
    533                         Type *adjType = candidate->get_type()->clone();
    534                         adjustExprType( adjType, newEnv, indexer );
    535                         renameTyVars( adjType );
    536                         PRINT(
    537                                 std::cerr << "unifying ";
    538                                 curDecl->get_type()->print( std::cerr );
    539                                 std::cerr << " with ";
    540                                 adjType->print( std::cerr );
    541                                 std::cerr << std::endl;
    542                         )
    543                         if ( unify( curDecl->get_type(), adjType, newEnv, newerNeed, newHave, newOpenVars, indexer ) ) {
    544                                 PRINT(
    545                                         std::cerr << "success!" << std::endl;
    546                                 )
    547                                 SymTab::Indexer newDecls( decls );
    548                                 addToIndexer( newHave, newDecls );
    549                                 Alternative newerAlt( newAlt );
    550                                 newerAlt.env = newEnv;
    551                                 assertf( candidate->get_uniqueId(), "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() );
    552 
    553                                 // everything with an empty idChain was pulled in by the current assertion.
    554                                 // add current assertion's idChain + current assertion's ID so that the correct inferParameters can be found.
    555                                 for ( auto & a : newerNeed ) {
    556                                         if ( a.second.idChain.empty() ) {
    557                                                 a.second.idChain = cur->second.idChain;
    558                                                 a.second.idChain.push_back( curDecl->get_uniqueId() );
    559                                         }
    560                                 }
    561 
    562                                 Expression *varExpr = data.combine( newerAlt.cvtCost );
    563                                 delete varExpr->get_result();
    564                                 varExpr->set_result( adjType->clone() );
    565                                 PRINT(
    566                                         std::cerr << "satisfying assertion " << curDecl->get_uniqueId() << " ";
    567                                         curDecl->print( std::cerr );
    568                                         std::cerr << " with declaration " << candidate->get_uniqueId() << " ";
    569                                         candidate->print( std::cerr );
    570                                         std::cerr << std::endl;
    571                                 )
    572                                 // follow the current assertion's ID chain to find the correct set of inferred parameters to add the candidate to (i.e. the set of inferred parameters belonging to the entity which requested the assertion parameter).
    573                                 InferredParams * inferParameters = &newerAlt.expr->get_inferParams();
    574                                 for ( UniqueId id : cur->second.idChain ) {
    575                                         inferParameters = (*inferParameters)[ id ].inferParams.get();
    576                                 }
    577                                 // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions
    578                                 (*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( candidate->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr );
    579                                 inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, level, indexer, out );
    580                         } else {
    581                                 delete adjType;
    582                         }
    583                 }
    584         }
     500                }
     501        }
     502
     503        /// Unique identifier for matching expression resolutions to their requesting expression
     504        UniqueId globalResnSlot = 0;
    585505
    586506        template< typename OutputIterator >
    587         void AlternativeFinder::Finder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) {
    588 //      PRINT(
    589 //          std::cerr << "inferParameters: assertions needed are" << std::endl;
    590 //          printAll( need, std::cerr, 8 );
    591 //          )
    592                 SymTab::Indexer decls( indexer );
    593                 // PRINT(
    594                 //      std::cerr << "============= original indexer" << std::endl;
    595                 //      indexer.print( std::cerr );
    596                 //      std::cerr << "============= new indexer" << std::endl;
    597                 //      decls.print( std::cerr );
    598                 // )
    599                 addToIndexer( have, decls );
    600                 AssertionSet newNeed;
    601                 PRINT(
    602                         std::cerr << "env is: " << std::endl;
    603                         newAlt.env.print( std::cerr, 0 );
    604                         std::cerr << std::endl;
    605                 )
    606 
    607                 inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, 0, indexer, out );
    608 //      PRINT(
    609 //          std::cerr << "declaration 14 is ";
    610 //          Declaration::declFromId
    611 //          *out++ = newAlt;
    612 //          )
     507        void AlternativeFinder::Finder::inferParameters( Alternative &newAlt, OutputIterator out ) {
     508                // Set need bindings for any unbound assertions
     509                UniqueId crntResnSlot = 0;  // matching ID for this expression's assertions
     510                for ( auto& assn : newAlt.need ) {
     511                        // skip already-matched assertions
     512                        if ( assn.info.resnSlot != 0 ) continue;
     513                        // assign slot for expression if needed
     514                        if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; }
     515                        // fix slot to assertion
     516                        assn.info.resnSlot = crntResnSlot;
     517                }
     518                // pair slot to expression
     519                if ( crntResnSlot != 0 ) { newAlt.expr->resnSlots.push_back( crntResnSlot ); }
     520
     521                // add to output list, assertion resolution is deferred
     522                *out++ = newAlt;
    613523        }
    614524
     
    951861                }
    952862                // build and validate new alternative
    953                 Alternative newAlt( appExpr, result.env, cost );
     863                Alternative newAlt{ appExpr, result.env, result.openVars, result.need, cost };
    954864                PRINT(
    955865                        std::cerr << "instantiate function success: " << appExpr << std::endl;
     
    957867                        printAssertionSet( result.need, std::cerr, 8 );
    958868                )
    959                 inferParameters( result.need, result.have, newAlt, result.openVars, out );
     869                inferParameters( newAlt, out );
    960870        }
    961871
     
    12021112
    12031113                // function may return struct or union value, in which case we need to add alternatives
    1204                 // for implicitconversions to each of the anonymous members, must happen after findMinCost
     1114                // for implicit conversions to each of the anonymous members, must happen after findMinCost
    12051115                // since anon conversions are never the cheapest expression
    12061116                for ( const Alternative & alt : winners ) {
     
    12341144                        if ( isLvalue( alt.expr ) ) {
    12351145                                alternatives.push_back(
    1236                                         Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } );
     1146                                        Alternative{ alt, new AddressExpr( alt.expr->clone() ), alt.cost } );
    12371147                        } // if
    12381148                } // for
     
    12401150
    12411151        void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) {
    1242                 alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } );
     1152                alternatives.push_back( Alternative{ expr->clone(), env } );
    12431153        }
    12441154
     
    12851195                AltList candidates;
    12861196                for ( Alternative & alt : finder.alternatives ) {
    1287                         AssertionSet needAssertions, haveAssertions;
    1288                         OpenVarSet openVars;
     1197                        AssertionSet needAssertions( alt.need.begin(), alt.need.end() );
     1198                        AssertionSet haveAssertions;
     1199                        OpenVarSet openVars{ alt.openVars };
    12891200
    12901201                        alt.env.extractOpenVars( openVars );
     
    13141225                                // count one safe conversion for each value that is thrown away
    13151226                                thisCost.incSafe( discardedValues );
    1316                                 Alternative newAlt( restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), alt.env,
    1317                                         alt.cost, thisCost );
    1318                                 inferParameters( needAssertions, haveAssertions, newAlt, openVars,
    1319                                         back_inserter( candidates ) );
     1227                                Alternative newAlt{
     1228                                        restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ),
     1229                                        alt.env, openVars, needAssertions, alt.cost, alt.cost + thisCost };
     1230                                inferParameters( newAlt, back_inserter( candidates ) );
    13201231                        } // if
    13211232                } // for
     
    13301241
    13311242        void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) {
    1332                 assertf( castExpr->get_result(), "Implicate virtual cast targets not yet supported." );
     1243                assertf( castExpr->get_result(), "Implicit virtual cast targets not yet supported." );
    13331244                AlternativeFinder finder( indexer, env );
    13341245                // don't prune here, since it's guaranteed all alternatives will have the same type
    13351246                finder.findWithoutPrune( castExpr->get_arg() );
    13361247                for ( Alternative & alt : finder.alternatives ) {
    1337                         alternatives.push_back( Alternative(
    1338                                 new VirtualCastExpr( alt.expr->clone(), castExpr->get_result()->clone() ),
    1339                                 alt.env, alt.cost ) );
     1248                        alternatives.push_back( Alternative{
     1249                                alt, new VirtualCastExpr{ alt.expr->clone(), castExpr->get_result()->clone() },
     1250                                alt.cost } );
    13401251                }
    13411252        }
     
    13441255                /// Gets name from untyped member expression (member must be NameExpr)
    13451256                const std::string& get_member_name( UntypedMemberExpr *memberExpr ) {
     1257                        if ( dynamic_cast< ConstantExpr * >( memberExpr->get_member() ) ) {
     1258                                SemanticError( memberExpr, "Indexed access to struct fields unsupported: " );
     1259                        } // if
    13461260                        NameExpr * nameExpr = dynamic_cast< NameExpr * >( memberExpr->get_member() );
    13471261                        assert( nameExpr );
     
    13621276                        // find member of the given type
    13631277                        if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
    1364                                 addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
     1278                                addAggMembers( structInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );
    13651279                        } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
    1366                                 addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
     1280                                addAggMembers( unionInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );
    13671281                        } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) {
    1368                                 addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() );
     1282                                addTupleMembers( tupleType, aggrExpr, *agg, cost, memberExpr->get_member() );
    13691283                        } // if
    13701284                } // for
     
    13721286
    13731287        void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) {
    1374                 alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) );
     1288                alternatives.push_back( Alternative{ memberExpr->clone(), env } );
    13751289        }
    13761290
     
    13851299                        // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
    13861300                        // can't construct in place and use vector::back
    1387                         Alternative newAlt( newExpr, env, Cost::zero, cost );
     1301                        Alternative newAlt{ newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost };
    13881302                        PRINT(
    13891303                                std::cerr << "decl is ";
     
    14031317                // not sufficient to clone here, because variable's type may have changed
    14041318                // since the VariableExpr was originally created.
    1405                 alternatives.push_back( Alternative( new VariableExpr( variableExpr->var ), env, Cost::zero ) );
     1319                alternatives.push_back( Alternative{ new VariableExpr{ variableExpr->var }, env } );
    14061320        }
    14071321
    14081322        void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) {
    1409                 alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) );
     1323                alternatives.push_back( Alternative{ constantExpr->clone(), env } );
    14101324        }
    14111325
     
    14131327                if ( sizeofExpr->get_isType() ) {
    14141328                        Type * newType = sizeofExpr->get_type()->clone();
    1415                         alternatives.push_back( Alternative( new SizeofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) );
     1329                        alternatives.push_back( Alternative{
     1330                                new SizeofExpr{ resolveTypeof( newType, indexer ) }, env } );
    14161331                } else {
    14171332                        // find all alternatives for the argument to sizeof
     
    14271342                        Alternative &choice = winners.front();
    14281343                        referenceToRvalueConversion( choice.expr, choice.cost );
    1429                         alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
     1344                        alternatives.push_back( Alternative{
     1345                                choice, new SizeofExpr( choice.expr->clone() ), Cost::zero } );
    14301346                } // if
    14311347        }
     
    14341350                if ( alignofExpr->get_isType() ) {
    14351351                        Type * newType = alignofExpr->get_type()->clone();
    1436                         alternatives.push_back( Alternative( new AlignofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) );
     1352                        alternatives.push_back( Alternative{
     1353                                new AlignofExpr{ resolveTypeof( newType, indexer ) }, env } );
    14371354                } else {
    14381355                        // find all alternatives for the argument to sizeof
     
    14481365                        Alternative &choice = winners.front();
    14491366                        referenceToRvalueConversion( choice.expr, choice.cost );
    1450                         alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
     1367                        alternatives.push_back( Alternative{
     1368                                choice, new AlignofExpr{ choice.expr->clone() }, Cost::zero } );
    14511369                } // if
    14521370        }
     
    14581376                for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
    14591377                        if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) {
    1460                                 alternatives.push_back( Alternative( new OffsetofExpr( aggInst->clone(), dwt ), env, Cost::zero ) );
     1378                                alternatives.push_back( Alternative{
     1379                                        new OffsetofExpr{ aggInst->clone(), dwt }, env } );
    14611380                                renameTypes( alternatives.back().expr );
    14621381                        } else {
     
    14771396
    14781397        void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) {
    1479                 alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) );
     1398                alternatives.push_back( Alternative{ offsetofExpr->clone(), env } );
    14801399        }
    14811400
    14821401        void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) {
    1483                 alternatives.push_back( Alternative( offsetPackExpr->clone(), env, Cost::zero ) );
     1402                alternatives.push_back( Alternative{ offsetPackExpr->clone(), env } );
    14841403        }
    14851404
     
    15011420                                Cost cost = Cost::zero;
    15021421                                Expression * newExpr = data.combine( cost );
    1503                                 alternatives.push_back( Alternative( new AttrExpr( newExpr, argType->clone() ), env, Cost::zero, cost ) );
     1422                                alternatives.push_back( Alternative{
     1423                                        new AttrExpr{ newExpr, argType->clone() }, env, OpenVarSet{},
     1424                                        AssertionList{}, Cost::zero, cost } );
    15041425                                for ( DeclarationWithType * retVal : function->returnVals ) {
    15051426                                        alternatives.back().expr->result = retVal->get_type()->clone();
     
    15401461                                Cost cost = Cost::zero;
    15411462                                Expression * newExpr = data.combine( cost );
    1542                                 alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) );
     1463                                alternatives.push_back( Alternative{
     1464                                        newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost } );
    15431465                                renameTypes( alternatives.back().expr );
    15441466                        } // for
     
    15551477                for ( const Alternative & first : firstFinder.alternatives ) {
    15561478                        for ( const Alternative & second : secondFinder.alternatives ) {
    1557                                 TypeEnvironment compositeEnv;
    1558                                 compositeEnv.simpleCombine( first.env );
     1479                                TypeEnvironment compositeEnv{ first.env };
    15591480                                compositeEnv.simpleCombine( second.env );
    1560 
    1561                                 LogicalExpr *newExpr = new LogicalExpr( first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() );
    1562                                 alternatives.push_back( Alternative( newExpr, compositeEnv, first.cost + second.cost ) );
     1481                                OpenVarSet openVars{ first.openVars };
     1482                                mergeOpenVars( openVars, second.openVars );
     1483                                AssertionSet need;
     1484                                cloneAll( first.need, need );
     1485                                cloneAll( second.need, need );
     1486
     1487                                LogicalExpr *newExpr = new LogicalExpr{
     1488                                        first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() };
     1489                                alternatives.push_back( Alternative{
     1490                                        newExpr, std::move(compositeEnv), std::move(openVars),
     1491                                        AssertionList( need.begin(), need.end() ), first.cost + second.cost } );
    15631492                        }
    15641493                }
     
    15811510                        for ( const Alternative & second : secondFinder.alternatives ) {
    15821511                                for ( const Alternative & third : thirdFinder.alternatives ) {
    1583                                         TypeEnvironment compositeEnv;
    1584                                         compositeEnv.simpleCombine( first.env );
     1512                                        TypeEnvironment compositeEnv{ first.env };
    15851513                                        compositeEnv.simpleCombine( second.env );
    15861514                                        compositeEnv.simpleCombine( third.env );
    1587 
     1515                                        OpenVarSet openVars{ first.openVars };
     1516                                        mergeOpenVars( openVars, second.openVars );
     1517                                        mergeOpenVars( openVars, third.openVars );
     1518                                        AssertionSet need;
     1519                                        cloneAll( first.need, need );
     1520                                        cloneAll( second.need, need );
     1521                                        cloneAll( third.need, need );
     1522                                        AssertionSet have;
     1523                                       
    15881524                                        // unify true and false types, then infer parameters to produce new alternatives
    1589                                         OpenVarSet openVars;
    1590                                         AssertionSet needAssertions, haveAssertions;
    1591                                         Alternative newAlt( 0, compositeEnv, first.cost + second.cost + third.cost );
    15921525                                        Type* commonType = nullptr;
    1593                                         if ( unify( second.expr->result, third.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
    1594                                                 ConditionalExpr *newExpr = new ConditionalExpr( first.expr->clone(), second.expr->clone(), third.expr->clone() );
     1526                                        if ( unify( second.expr->result, third.expr->result, compositeEnv,
     1527                                                        need, have, openVars, indexer, commonType ) ) {
     1528                                                ConditionalExpr *newExpr = new ConditionalExpr{
     1529                                                        first.expr->clone(), second.expr->clone(), third.expr->clone() };
    15951530                                                newExpr->result = commonType ? commonType : second.expr->result->clone();
    15961531                                                // convert both options to the conditional result type
    1597                                                 newAlt.cost += computeExpressionConversionCost( newExpr->arg2, newExpr->result, indexer, newAlt.env );
    1598                                                 newAlt.cost += computeExpressionConversionCost( newExpr->arg3, newExpr->result, indexer, newAlt.env );
    1599                                                 newAlt.expr = newExpr;
    1600                                                 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
     1532                                                Cost cost = first.cost + second.cost + third.cost;
     1533                                                cost += computeExpressionConversionCost(
     1534                                                        newExpr->arg2, newExpr->result, indexer, compositeEnv );
     1535                                                cost += computeExpressionConversionCost(
     1536                                                        newExpr->arg3, newExpr->result, indexer, compositeEnv );
     1537                                                // output alternative
     1538                                                Alternative newAlt{
     1539                                                        newExpr, std::move(compositeEnv), std::move(openVars),
     1540                                                        AssertionList( need.begin(), need.end() ), cost };
     1541                                                inferParameters( newAlt, back_inserter( alternatives ) );
    16011542                                        } // if
    16021543                                } // for
     
    16111552                secondFinder.findWithAdjustment( commaExpr->get_arg2() );
    16121553                for ( const Alternative & alt : secondFinder.alternatives ) {
    1613                         alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) );
     1554                        alternatives.push_back( Alternative{
     1555                                alt, new CommaExpr{ newFirstArg->clone(), alt.expr->clone() }, alt.cost } );
    16141556                } // for
    16151557                delete newFirstArg;
     
    16261568                for ( const Alternative & first : firstFinder.alternatives ) {
    16271569                        for ( const Alternative & second : secondFinder.alternatives ) {
    1628                                 TypeEnvironment compositeEnv;
    1629                                 compositeEnv.simpleCombine( first.env );
     1570                                TypeEnvironment compositeEnv{ first.env };
    16301571                                compositeEnv.simpleCombine( second.env );
    1631                                 OpenVarSet openVars;
    1632                                 AssertionSet needAssertions, haveAssertions;
    1633                                 Alternative newAlt( 0, compositeEnv, first.cost + second.cost );
     1572                                OpenVarSet openVars{ first.openVars };
     1573                                mergeOpenVars( openVars, second.openVars );
     1574                                AssertionSet need;
     1575                                cloneAll( first.need, need );
     1576                                cloneAll( second.need, need );
     1577                                AssertionSet have;
     1578
    16341579                                Type* commonType = nullptr;
    1635                                 if ( unify( first.expr->result, second.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
    1636                                         RangeExpr * newExpr = new RangeExpr( first.expr->clone(), second.expr->clone() );
     1580                                if ( unify( first.expr->result, second.expr->result, compositeEnv, need, have,
     1581                                                openVars, indexer, commonType ) ) {
     1582                                        RangeExpr * newExpr =
     1583                                                new RangeExpr{ first.expr->clone(), second.expr->clone() };
    16371584                                        newExpr->result = commonType ? commonType : first.expr->result->clone();
    1638                                         newAlt.expr = newExpr;
    1639                                         inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
     1585                                        Alternative newAlt{
     1586                                                newExpr, std::move(compositeEnv), std::move(openVars),
     1587                                                AssertionList( need.begin(), need.end() ), first.cost + second.cost };
     1588                                        inferParameters( newAlt, back_inserter( alternatives ) );
    16401589                                } // if
    16411590                        } // for
     
    16551604
    16561605                        TypeEnvironment compositeEnv;
    1657                         simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv );
    1658                         alternatives.push_back(
    1659                                 Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } );
     1606                        OpenVarSet openVars;
     1607                        AssertionSet need;
     1608                        for ( const Alternative& alt : alts ) {
     1609                                compositeEnv.simpleCombine( alt.env );
     1610                                mergeOpenVars( openVars, alt.openVars );
     1611                                cloneAll( alt.need, need );
     1612                        }
     1613                       
     1614                        alternatives.push_back( Alternative{
     1615                                new TupleExpr{ exprs }, std::move(compositeEnv), std::move(openVars),
     1616                                AssertionList( need.begin(), need.end() ), sumCost( alts ) } );
    16601617                } // for
    16611618        }
    16621619
    16631620        void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) {
    1664                 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
     1621                alternatives.push_back( Alternative{ tupleExpr->clone(), env } );
    16651622        }
    16661623
    16671624        void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) {
    1668                 alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) );
     1625                alternatives.push_back( Alternative{ impCpCtorExpr->clone(), env } );
    16691626        }
    16701627
     
    16751632                finder.findWithoutPrune( ctorExpr->get_callExpr() );
    16761633                for ( Alternative & alt : finder.alternatives ) {
    1677                         alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) );
     1634                        alternatives.push_back( Alternative{
     1635                                alt, new ConstructorExpr( alt.expr->clone() ), alt.cost } );
    16781636                }
    16791637        }
    16801638
    16811639        void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) {
    1682                 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
     1640                alternatives.push_back( Alternative{ tupleExpr->clone(), env } );
    16831641        }
    16841642
    16851643        void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) {
    1686                 alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) );
     1644                alternatives.push_back( Alternative{ tupleAssignExpr->clone(), env } );
    16871645        }
    16881646
     
    16931651                        // ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked"
    16941652                        UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() );
    1695                         alternatives.push_back( Alternative( newUnqExpr, alt.env, alt.cost ) );
     1653                        alternatives.push_back( Alternative{ alt, newUnqExpr, alt.cost } );
    16961654                }
    16971655        }
     
    17011659                ResolvExpr::resolveStmtExpr( newStmtExpr, indexer );
    17021660                // xxx - this env is almost certainly wrong, and needs to somehow contain the combined environments from all of the statements in the stmtExpr...
    1703                 alternatives.push_back( Alternative( newStmtExpr, env, Cost::zero ) );
     1661                alternatives.push_back( Alternative{ newStmtExpr, env } );
    17041662        }
    17051663
     
    17231681                        for ( Alternative & alt : finder.get_alternatives() ) {
    17241682                                TypeEnvironment newEnv( alt.env );
    1725                                 AssertionSet needAssertions, haveAssertions;
    1726                                 OpenVarSet openVars;  // find things in env that don't have a "representative type" and claim those are open vars?
     1683                                AssertionSet need;
     1684                                cloneAll( alt.need, need );
     1685                                AssertionSet have;
     1686                                OpenVarSet openVars( alt.openVars ); 
     1687                                // xxx - find things in env that don't have a "representative type" and claim
     1688                                // those are open vars?
    17271689                                PRINT(
    17281690                                        std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl;
    17291691                                )
    1730                                 // It's possible that a cast can throw away some values in a multiply-valued expression.  (An example is a
    1731                                 // cast-to-void, which casts from one value to zero.)  Figure out the prefix of the subexpression results
    1732                                 // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
    1733                                 // to.
     1692                                // It's possible that a cast can throw away some values in a multiply-valued
     1693                                // expression. (An example is a cast-to-void, which casts from one value to
     1694                                // zero.)  Figure out the prefix of the subexpression results that are cast
     1695                                // directly.  The candidate is invalid if it has fewer results than there are
     1696                                // types to cast to.
    17341697                                int discardedValues = alt.expr->result->size() - toType->size();
    17351698                                if ( discardedValues < 0 ) continue;
    1736                                 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
    1737                                 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
     1699                                // xxx - may need to go into tuple types and extract relevant types and use
     1700                                // unifyList. Note that currently, this does not allow casting a tuple to an
     1701                                // atomic type (e.g. (int)([1, 2, 3]))
     1702                               
    17381703                                // unification run for side-effects
    1739                                 unify( toType, alt.expr->result, newEnv, needAssertions, haveAssertions, openVars, indexer ); // xxx - do some inspecting on this line... why isn't result bound to initAlt.type??
     1704                                unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer );
     1705                                // xxx - do some inspecting on this line... why isn't result bound to initAlt.type?
    17401706
    17411707                                Cost thisCost = castCost( alt.expr->result, toType, indexer, newEnv );
     
    17431709                                        // count one safe conversion for each value that is thrown away
    17441710                                        thisCost.incSafe( discardedValues );
    1745                                         Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost );
    1746                                         inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) );
     1711                                        Alternative newAlt{
     1712                                                new InitExpr{
     1713                                                        restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() },
     1714                                                std::move(newEnv), std::move(openVars),
     1715                                                AssertionList( need.begin(), need.end() ), alt.cost, thisCost };
     1716                                        inferParameters( newAlt, back_inserter( candidates ) );
    17471717                                }
    17481718                        }
  • src/ResolvExpr/AlternativeFinder.h

    r9b086ca rcde3891  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sat May 16 23:56:12 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Jul 26 11:24:00 2017
    13 // Update Count     : 4
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Fri Oct -5 10:01:00 2018
     13// Update Count     : 5
    1414//
    1515
     
    2424#include "ResolvExpr/Cost.h"             // for Cost, Cost::infinity
    2525#include "ResolvExpr/TypeEnvironment.h"  // for AssertionSet, OpenVarSet
     26#include "ResolvMode.h"                  // for ResolvMode
    2627#include "SynTree/Visitor.h"             // for Visitor
    2728#include "SynTree/SynTree.h"             // for Visitor Nodes
     
    6869                }
    6970
    70                 void find( Expression *expr, bool adjust = false, bool prune = true, bool failFast = true );
     71                void find( Expression *expr, ResolvMode mode = ResolvMode{} );
    7172                /// Calls find with the adjust flag set; adjustment turns array and function types into equivalent pointer types
    7273                void findWithAdjustment( Expression *expr );
  • src/ResolvExpr/ConversionCost.cc

    r9b086ca rcde3891  
    2828
    2929namespace ResolvExpr {
    30         const Cost Cost::zero =      Cost(  0,  0,  0,  0 );
    31         const Cost Cost::infinity =  Cost( -1, -1, -1, -1 );
    32         const Cost Cost::unsafe =    Cost(  1,  0,  0,  0 );
    33         const Cost Cost::poly =      Cost(  0,  1,  0,  0 );
    34         const Cost Cost::safe =      Cost(  0,  0,  1,  0 );
    35         const Cost Cost::reference = Cost(  0,  0,  0,  1 );
     30        const Cost Cost::zero =      Cost{  0,  0,  0,  0,  0,  0 };
     31        const Cost Cost::infinity =  Cost{ -1, -1, -1, -1,  1, -1 };
     32        const Cost Cost::unsafe =    Cost{  1,  0,  0,  0,  0,  0 };
     33        const Cost Cost::poly =      Cost{  0,  1,  0,  0,  0,  0 };
     34        const Cost Cost::safe =      Cost{  0,  0,  1,  0,  0,  0 };
     35        const Cost Cost::var =       Cost{  0,  0,  0,  1,  0,  0 };
     36        const Cost Cost::spec =      Cost{  0,  0,  0,  0, -1,  0 };
     37        const Cost Cost::reference = Cost{  0,  0,  0,  0,  0,  1 };
    3638
    3739#if 0
  • src/ResolvExpr/Cost.h

    r9b086ca rcde3891  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 09:39:50 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:35:55 2017
    13 // Update Count     : 5
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Fri Oct 05 14:32:00 2018
     13// Update Count     : 7
    1414//
    1515
     
    2121        class Cost {
    2222          private:
    23                 Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost );
     23                Cost( int unsafeCost, int polyCost, int safeCost, int varCost, int specCost,
     24                        int referenceCost );
    2425
    2526          public:
     
    2728                Cost & incPoly( int inc = 1 );
    2829                Cost & incSafe( int inc = 1 );
     30                Cost & incVar( int inc = 1 );
     31                Cost & decSpec( int inc = 1 );
    2932                Cost & incReference( int inc = 1 );
    3033
     
    3235                int get_polyCost() const { return polyCost; }
    3336                int get_safeCost() const { return safeCost; }
     37                int get_varCost() const { return varCost; }
     38                int get_specCost() const { return specCost; }
    3439                int get_referenceCost() const { return referenceCost; }
    3540
     
    4146                bool operator!=( const Cost &other ) const;
    4247                friend std::ostream &operator<<( std::ostream &os, const Cost &cost );
     48                // returns negative for *this < other, 0 for *this == other, positive for *this > other
     49                int compare( const Cost &other ) const;
    4350
    4451                static const Cost zero;
     
    4855                static const Cost poly;
    4956                static const Cost safe;
     57                static const Cost var;
     58                static const Cost spec;
    5059                static const Cost reference;
     60
    5161          private:
    52                 int compare( const Cost &other ) const;
    53 
    54                 int unsafeCost;
    55                 int polyCost;
    56                 int safeCost;
    57                 int referenceCost;
     62                int unsafeCost;     ///< Unsafe (narrowing) conversions
     63                int polyCost;       ///< Count of parameters and return values bound to some poly type
     64                int safeCost;       ///< Safe (widening) conversions
     65                int varCost;        ///< Count of polymorphic type variables
     66                int specCost;       ///< Polymorphic type specializations (type assertions), negative cost
     67                int referenceCost;  ///< reference conversions
    5868        };
    5969
    60         inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost ) : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), referenceCost( referenceCost ) {}
     70        inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int varCost, int specCost,
     71                        int referenceCost )
     72                : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), varCost( varCost ),
     73                  specCost( specCost ), referenceCost( referenceCost ) {}
    6174
    6275        inline Cost & Cost::incUnsafe( int inc ) {
     
    7588                if ( *this == infinity ) return *this;
    7689                safeCost += inc;
     90                return *this;
     91        }
     92
     93        inline Cost & Cost::incVar( int inc ) {
     94                if ( *this == infinity ) return *this;
     95                varCost += inc;
     96                return *this;
     97        }
     98
     99        inline Cost& Cost::decSpec( int dec ) {
     100                if ( *this == infinity ) return *this;
     101                specCost -= dec;
    77102                return *this;
    78103        }
     
    86111        inline Cost Cost::operator+( const Cost &other ) const {
    87112                if ( *this == infinity || other == infinity ) return infinity;
    88                 return Cost( unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost, referenceCost + other.referenceCost );
     113                return Cost{
     114                        unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost,
     115                        varCost + other.varCost, specCost + other.specCost,
     116                        referenceCost + other.referenceCost };
    89117        }
    90118
    91119        inline Cost Cost::operator-( const Cost &other ) const {
    92120                if ( *this == infinity || other == infinity ) return infinity;
    93                 return Cost( unsafeCost - other.unsafeCost, polyCost - other.polyCost, safeCost - other.safeCost, referenceCost - other.referenceCost );
     121                return Cost{
     122                        unsafeCost - other.unsafeCost, polyCost - other.polyCost, safeCost - other.safeCost,
     123                        varCost - other.varCost, specCost - other.specCost,
     124                        referenceCost - other.referenceCost };
    94125        }
    95126
     
    103134                polyCost += other.polyCost;
    104135                safeCost += other.safeCost;
     136                varCost += other.varCost;
     137                specCost += other.specCost;
    105138                referenceCost += other.referenceCost;
    106139                return *this;
     
    123156                } else if ( safeCost < other.safeCost ) {
    124157                        return true;
     158                } else if ( varCost > other.varCost ) {
     159                        return false;
     160                } else if ( varCost < other.varCost ) {
     161                        return true;
     162                } else if ( specCost > other.specCost ) {
     163                        return false;
     164                } else if ( specCost > other.specCost ) {
     165                        return true;
    125166                } else if ( referenceCost > other.referenceCost ) {
    126167                        return false;
     
    130171                        return false;
    131172                } // if
     173        }
     174
     175        inline int Cost::compare( const Cost &other ) const {
     176                if ( *this == infinity ) return +1;
     177                if ( other == infinity ) return -1;
     178
     179                int c = unsafeCost - other.unsafeCost; if ( c ) return c;
     180                c = polyCost - other.polyCost; if ( c ) return c;
     181                c = safeCost - other.safeCost; if ( c ) return c;
     182                c = varCost - other.varCost; if ( c ) return c;
     183                c = specCost - other.specCost; if ( c ) return c;
     184                return referenceCost - other.referenceCost;
    132185        }
    133186
     
    136189                        && polyCost == other.polyCost
    137190                        && safeCost == other.safeCost
     191                        && varCost == other.varCost
     192                        && specCost == other.specCost
    138193                        && referenceCost == other.referenceCost;
    139194        }
     
    144199
    145200        inline std::ostream &operator<<( std::ostream &os, const Cost &cost ) {
    146                 os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", " << cost.safeCost << ", " << cost.referenceCost << " )";
    147                 return os;
     201                return os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", "
     202                          << cost.safeCost << ", " << cost.varCost << ", " << cost.specCost << ", "
     203                          << cost.referenceCost << " )";
    148204        }
    149205} // namespace ResolvExpr
  • src/ResolvExpr/ResolveTypeof.cc

    r9b086ca rcde3891  
    6767                std::cerr << std::endl;
    6868#endif
    69                 if ( typeofType->expr ) {
     69                // pass on null expression
     70                if ( ! typeofType->expr ) return typeofType;
     71
     72                bool isBasetypeof = typeofType->is_basetypeof;
     73                auto oldQuals = typeofType->get_qualifiers().val;
     74
     75                Type* newType;
     76                if ( TypeExpr* tyExpr = dynamic_cast<TypeExpr*>(typeofType->expr) ) {
     77                        // typeof wrapping type
     78                        newType = tyExpr->type;
     79                        tyExpr->type = nullptr;
     80                        delete tyExpr;
     81                } else {
     82                        // typeof wrapping expression
    7083                        Expression * newExpr = resolveInVoidContext( typeofType->expr, indexer );
    7184                        assert( newExpr->result && ! newExpr->result->isVoid() );
    72                         Type * newType = newExpr->result;
     85                        newType = newExpr->result;
    7386                        newExpr->result = nullptr;
    7487                        delete typeofType;
    7588                        delete newExpr;
    76                         return newType;
    77                 } // if
    78                 return typeofType;
     89                }
     90
     91                // clear qualifiers for base, combine with typeoftype quals in any case
     92                if ( isBasetypeof ) {
     93                        // replace basetypeof(<enum>) by int
     94                        if ( dynamic_cast<EnumInstType*>(newType) ) {
     95                                Type* newerType =
     96                                        new BasicType{ newType->get_qualifiers(), BasicType::SignedInt,
     97                                        newType->attributes };
     98                                delete newType;
     99                                newType = newerType;
     100                        }
     101                        newType->get_qualifiers().val
     102                                = ( newType->get_qualifiers().val & ~Type::Qualifiers::Mask ) | oldQuals;
     103                } else {
     104                        newType->get_qualifiers().val |= oldQuals;
     105                }
     106               
     107                return newType;
    79108        }
    80109} // namespace ResolvExpr
  • src/ResolvExpr/Resolver.cc

    r9b086ca rcde3891  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:17:01 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Feb 17 11:19:40 2018
    13 // Update Count     : 213
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Fri Oct 05 09:43:00 2018
     13// Update Count     : 214
    1414//
    1515
    16 #include <stddef.h>                      // for NULL
    1716#include <cassert>                       // for strict_dynamic_cast, assert
    1817#include <memory>                        // for allocator, allocator_traits<...
    1918#include <tuple>                         // for get
    20 #include <vector>
     19#include <vector>                        // for vector
    2120
    2221#include "Alternative.h"                 // for Alternative, AltList
     
    3130#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
    3231#include "Resolver.h"
     32#include "ResolvMode.h"                  // for ResolvMode
     33#include "SymTab/Autogen.h"              // for SizeType
    3334#include "SymTab/Indexer.h"              // for Indexer
    3435#include "SynTree/Declaration.h"         // for ObjectDecl, TypeDecl, Declar...
     
    168169
    169170        namespace {
    170                 void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {
     171                void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{} ) {
    171172                        assertf( untyped, "expected a non-null expression." );
     173
     174                        // xxx - this isn't thread-safe, but should work until we parallelize the resolver
     175                        static unsigned recursion_level = 0;
     176
     177                        ++recursion_level;
    172178                        TypeEnvironment env;
    173179                        AlternativeFinder finder( indexer, env );
    174                         finder.find( untyped, adjust, prune, failFast );
     180                        finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
     181                        --recursion_level;
    175182
    176183                        #if 0
     
    185192                        #endif
    186193
     194                        // produce filtered list of alternatives
    187195                        AltList candidates;
    188196                        for ( Alternative & alt : finder.get_alternatives() ) {
     
    192200                        }
    193201
    194                         // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining
    195                         // choose the lowest cost expression among the candidates
     202                        // produce invalid error if no candidates
     203                        if ( candidates.empty() ) {
     204                                SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
     205                        }
     206
     207                        // search for cheapest candidate
    196208                        AltList winners;
    197                         findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
    198                         if ( winners.size() == 0 ) {
    199                                 SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
    200                         } else if ( winners.size() != 1 ) {
     209                        bool seen_undeleted = false;
     210                        for ( unsigned i = 0; i < candidates.size(); ++i ) {
     211                                int c = winners.empty() ? -1 : candidates[i].cost.compare( winners.front().cost );
     212
     213                                if ( c > 0 ) continue; // skip more expensive than winner
     214
     215                                if ( c < 0 ) {
     216                                        // reset on new cheapest
     217                                        seen_undeleted = ! findDeletedExpr( candidates[i].expr );
     218                                        winners.clear();
     219                                } else /* if ( c == 0 ) */ {
     220                                        if ( findDeletedExpr( candidates[i].expr ) ) {
     221                                                // skip deleted expression if already seen one equivalent-cost not
     222                                                if ( seen_undeleted ) continue;
     223                                        } else if ( ! seen_undeleted ) {
     224                                                // replace list of equivalent-cost deleted expressions with one non-deleted
     225                                                winners.clear();
     226                                                seen_undeleted = true;
     227                                        }
     228                                }
     229
     230                                winners.emplace_back( std::move( candidates[i] ) );
     231                        }
     232
     233                        // promote alternative.cvtCost to .cost
     234                        // xxx - I don't know why this is done, but I'm keeping the behaviour from findMinCost
     235                        for ( Alternative& winner : winners ) {
     236                                winner.cost = winner.cvtCost;
     237                        }
     238
     239                        // produce ambiguous errors, if applicable
     240                        if ( winners.size() != 1 ) {
    201241                                std::ostringstream stream;
    202242                                stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n";
     
    207247                        }
    208248
    209                         // there is one unambiguous interpretation - move the expression into the with statement
    210                         Alternative & choice = winners.front();
    211                         if ( findDeletedExpr( choice.expr ) ) {
     249                        // single selected choice
     250                        Alternative& choice = winners.front();
     251
     252                        // fail on only expression deleted
     253                        if ( ! seen_undeleted ) {
    212254                                SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " );
    213255                        }
     256
     257                        // xxx - check for ambiguous expressions
     258
     259                        // output selected choice
    214260                        alt = std::move( choice );
    215261                }
    216262
    217263                /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages
    218                 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {
     264                void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) {
    219265                        if ( ! untyped ) return;
    220266                        Alternative choice;
    221                         findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast );
     267                        findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode );
    222268                        finishExpr( choice.expr, choice.env, untyped->env );
    223269                        delete untyped;
     
    250296                untyped.arg = expr;
    251297                Alternative choice;
    252                 findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true );
     298                findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment() );
    253299                CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr );
    254300                env = std::move( choice.env );
     
    357403
    358404        void Resolver::previsit( ObjectDecl *objectDecl ) {
    359                 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that class-variable
    360                 // initContext is changed multiple time because the LHS is analysed twice. The second analysis changes
    361                 // initContext because of a function type can contain object declarations in the return and parameter types. So
    362                 // each value of initContext is retained, so the type on the first analysis is preserved and used for selecting
    363                 // the RHS.
     405                // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that
     406                // class-variable initContext is changed multiple time because the LHS is analysed twice.
     407                // The second analysis changes initContext because of a function type can contain object
     408                // declarations in the return and parameter types. So each value of initContext is
     409                // retained, so the type on the first analysis is preserved and used for selecting the RHS.
    364410                GuardValue( currentObject );
    365411                currentObject = CurrentObject( objectDecl->get_type() );
     
    397443
    398444        void Resolver::postvisit( FunctionDecl *functionDecl ) {
    399                 // default value expressions have an environment which shouldn't be there and trips up later passes.
    400                 // xxx - it might be necessary to somehow keep the information from this environment, but I can't currently
    401                 // see how it's useful.
     445                // default value expressions have an environment which shouldn't be there and trips up
     446                // later passes.
     447                // xxx - it might be necessary to somehow keep the information from this environment, but I
     448                // can't currently see how it's useful.
    402449                for ( Declaration * d : functionDecl->type->parameters ) {
    403450                        if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) {
     
    749796                initExpr->expr = nullptr;
    750797                std::swap( initExpr->env, newExpr->env );
    751                 // InitExpr may have inferParams in the case where the expression specializes a function pointer,
    752                 // and newExpr may already have inferParams of its own, so a simple swap is not sufficient.
     798                // InitExpr may have inferParams in the case where the expression specializes a function
     799                // pointer, and newExpr may already have inferParams of its own, so a simple swap is not
     800                // sufficient.
    753801                newExpr->spliceInferParams( initExpr );
    754802                delete initExpr;
    755803
    756                 // get the actual object's type (may not exactly match what comes back from the resolver due to conversions)
     804                // get the actual object's type (may not exactly match what comes back from the resolver
     805                // due to conversions)
    757806                Type * initContext = currentObject.getCurrentType();
    758807
     
    766815                                        if ( isCharType( pt->get_base() ) ) {
    767816                                                if ( CastExpr *ce = dynamic_cast< CastExpr * >( newExpr ) ) {
    768                                                         // strip cast if we're initializing a char[] with a char *, e.g.  char x[] = "hello";
     817                                                        // strip cast if we're initializing a char[] with a char *,
     818                                                        // e.g.  char x[] = "hello";
    769819                                                        newExpr = ce->get_arg();
    770820                                                        ce->set_arg( nullptr );
     
    788838                // move cursor into brace-enclosed initializer-list
    789839                currentObject.enterListInit();
    790                 // xxx - fix this so that the list isn't copied, iterator should be used to change current element
     840                // xxx - fix this so that the list isn't copied, iterator should be used to change current
     841                // element
    791842                std::list<Designation *> newDesignations;
    792843                for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) {
    793                         // iterate designations and initializers in pairs, moving the cursor to the current designated object and resolving
    794                         // the initializer against that object.
     844                        // iterate designations and initializers in pairs, moving the cursor to the current
     845                        // designated object and resolving the initializer against that object.
    795846                        Designation * des = std::get<0>(p);
    796847                        Initializer * init = std::get<1>(p);
     
    822873                // fall back on C-style initializer
    823874                delete ctorInit->get_ctor();
    824                 ctorInit->set_ctor( NULL );
     875                ctorInit->set_ctor( nullptr );
    825876                delete ctorInit->get_dtor();
    826                 ctorInit->set_dtor( NULL );
     877                ctorInit->set_dtor( nullptr );
    827878                maybeAccept( ctorInit->get_init(), *visitor );
    828879        }
     
    867918
    868919                // xxx - todo -- what about arrays?
    869                 // if ( dtor == NULL && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
     920                // if ( dtor == nullptr && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
    870921                //      // can reduce the constructor down to a SingleInit using the
    871922                //      // second argument from the ctor call, since
    872923                //      delete ctorInit->get_ctor();
    873                 //      ctorInit->set_ctor( NULL );
     924                //      ctorInit->set_ctor( nullptr );
    874925
    875926                //      Expression * arg =
  • src/ResolvExpr/TypeEnvironment.cc

    r9b086ca rcde3891  
    120120
    121121        const EqvClass* TypeEnvironment::lookup( const std::string &var ) const {
    122                 for ( std::list< EqvClass >::const_iterator i = env.begin(); i != env.end(); ++i ) {
     122                for ( ClassList::const_iterator i = env.begin(); i != env.end(); ++i ) {
    123123                        if ( i->vars.find( var ) != i->vars.end() ) return &*i;
    124124                } // for
     
    168168
    169169        void TypeEnvironment::makeSubstitution( TypeSubstitution &sub ) const {
    170                 for ( std::list< EqvClass >::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) {
     170                for ( ClassList::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) {
    171171                        for ( std::set< std::string >::const_iterator theVar = theClass->vars.begin(); theVar != theClass->vars.end(); ++theVar ) {
    172172                                if ( theClass->type ) {
     
    188188        }
    189189
    190         std::list< EqvClass >::iterator TypeEnvironment::internal_lookup( const std::string &var ) {
    191                 for ( std::list< EqvClass >::iterator i = env.begin(); i != env.end(); ++i ) {
     190        TypeEnvironment::ClassList::iterator TypeEnvironment::internal_lookup( const std::string &var ) {
     191                for ( ClassList::iterator i = env.begin(); i != env.end(); ++i ) {
    192192                        if ( i->vars.count( var ) ) return i;
    193193                } // for
     
    199199        }
    200200
     201        // xxx -- this should maybe be worrying about iterator invalidation (see resolv-proto)
     202        bool TypeEnvironment::mergeBound( EqvClass& to, const EqvClass& from, OpenVarSet& openVars, const SymTab::Indexer& indexer ) {
     203                if ( from.type ) {
     204                        if ( to.type ) {
     205                                // attempt to unify bound types
     206                                std::unique_ptr<Type> toType{ to.type->clone() }, fromType{ from.type->clone() };
     207                                WidenMode widenMode{ to.allowWidening, from.allowWidening };
     208                                Type* common = nullptr;
     209                                AssertionSet need, have;
     210                                if ( unifyInexact( toType.get(), fromType.get(), *this, need, have, openVars, widenMode, indexer, common ) ) {
     211                                        // unifies, set common type if necessary
     212                                        if ( common ) {
     213                                                common->get_qualifiers() = Type::Qualifiers{};
     214                                                to.set_type( common );
     215                                        }
     216                                } else return false; // cannot unify
     217                        } else {
     218                                to.type = from.type->clone();
     219                        }
     220                }
     221
     222                // unify widening if matches
     223                to.allowWidening &= from.allowWidening;
     224                return true;
     225        }
     226
     227        // xxx -- this should maybe be worrying about iterator invalidation (see resolv-proto)
     228        bool TypeEnvironment::mergeClasses( TypeEnvironment::ClassList::iterator to, TypeEnvironment::ClassList::iterator from, OpenVarSet& openVars, const SymTab::Indexer& indexer ) {
     229                EqvClass& r = *to;
     230                EqvClass& s = *from;
     231
     232                // ensure bounds match
     233                if ( ! mergeBound( r, s, openVars, indexer ) ) return false;
     234
     235                // check safely bindable
     236                if ( r.type && occursIn( r.type, s.vars.begin(), s.vars.end(), *this ) ) return false;
     237               
     238                // merge classes in
     239                r.vars.insert( s.vars.begin(), s.vars.end() );
     240                r.allowWidening &= s.allowWidening;
     241                env.erase( from );
     242
     243                return true;
     244        }
     245
     246        bool TypeEnvironment::combine( const TypeEnvironment& o, OpenVarSet& openVars, const SymTab::Indexer& indexer ) {
     247                // short-circuit easy cases
     248                if ( o.isEmpty() ) return true;
     249                if ( isEmpty() ) {
     250                        simpleCombine( o );
     251                        return true;
     252                }
     253
     254                // merge classes
     255                for ( auto ct = o.env.begin(); ct != o.env.end(); ++ct ) {
     256                        const EqvClass& c = *ct;
     257
     258                        // typeclass in local environment bound to c
     259                        auto rt = env.end();
     260
     261                        // look for first existing bound variable
     262                        auto vt = c.vars.begin();
     263                        for ( ; vt != c.vars.end(); ++vt ) {
     264                                rt = internal_lookup( *vt );
     265                                if ( rt != env.end() ) break;
     266                        }
     267
     268                        if ( rt != env.end() ) {  // c needs to be merged into *rt
     269                                EqvClass& r = *rt;
     270                                // merge bindings
     271                                if ( ! mergeBound( r, c, openVars, indexer ) ) return false;
     272                                // merge previous unbound variables into this class, checking occurs if needed
     273                                if ( r.type ) for ( auto ut = c.vars.begin(); ut != vt; ++ut ) {
     274                                        if ( occurs( r.type, *ut, *this ) ) return false;
     275                                        r.vars.insert( *ut );
     276                                } else { r.vars.insert( c.vars.begin(), vt ); }
     277                                // merge subsequent variables into this class (skipping *vt, already there)
     278                                while ( ++vt != c.vars.end() ) {
     279                                        auto st = internal_lookup( *vt );
     280                                        if ( st == env.end() ) {
     281                                                // unbound, safe to add if passes occurs
     282                                                if ( r.type && occurs( r.type, *vt, *this ) ) return false;
     283                                                r.vars.insert( *vt );
     284                                        } else if ( st != rt ) {
     285                                                // bound, but not to the same class
     286                                                if ( ! mergeClasses( rt, st, openVars, indexer ) ) return false;
     287                                        }   // ignore bound into the same class
     288                                }
     289                        } else {  // no variables in c bound; just copy up
     290                                env.push_back( c );
     291                        }
     292                }
     293
     294                // merged all classes
     295                return true;
     296        }
     297
    201298        void TypeEnvironment::extractOpenVars( OpenVarSet &openVars ) const {
    202                 for ( std::list< EqvClass >::const_iterator eqvClass = env.begin(); eqvClass != env.end(); ++eqvClass ) {
     299                for ( ClassList::const_iterator eqvClass = env.begin(); eqvClass != env.end(); ++eqvClass ) {
    203300                        for ( std::set< std::string >::const_iterator var = eqvClass->vars.begin(); var != eqvClass->vars.end(); ++var ) {
    204301                                openVars[ *var ] = eqvClass->data;
  • src/ResolvExpr/TypeEnvironment.h

    r9b086ca rcde3891  
    3939        // declarations.
    4040        //
    41         // I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this comparator.
     41        // I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this
     42        // comparator.
    4243        //
    4344        // Note: since this compares pointers for position, minor changes in the source file that affect
    4445        // memory layout can alter compilation time in unpredictable ways. For example, the placement
    4546        // of a line directive can reorder type pointers with respect to each other so that assertions
    46         // are seen in different orders, causing a potentially different number of unification calls when
    47         // resolving assertions. I've seen a TU go from 36 seconds to 27 seconds by reordering line directives
    48         // alone, so it would be nice to fix this comparison so that assertions compare more consistently.
    49         // I've tried to modify this to compare on mangle name instead of type as the second comparator, but
    50         // this causes some assertions to never be recorded. More investigation is needed.
     47        // are seen in different orders, causing a potentially different number of unification calls
     48        // when resolving assertions. I've seen a TU go from 36 seconds to 27 seconds by reordering
     49        // line directives alone, so it would be nice to fix this comparison so that assertions compare
     50        // more consistently. I've tried to modify this to compare on mangle name instead of type as
     51        // the second comparator, but this causes some assertions to never be recorded. More
     52        // investigation is needed.
    5153        struct AssertCompare {
    5254                bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const {
     
    5759        };
    5860        struct AssertionSetValue {
    59                 bool isUsed;
    60                 // chain of Unique IDs of the assertion declarations. The first ID in the chain is the ID of an assertion on the current type,
    61                 // with each successive ID being the ID of an assertion pulled in by the previous ID. The last ID in the chain is
    62                 // the ID of the assertion that pulled in the current assertion.
    63                 std::list< UniqueId > idChain;
     61                bool isUsed;        ///< True if assertion needs to be resolved
     62                UniqueId resnSlot;  ///< ID of slot assertion belongs to
     63
     64                AssertionSetValue() : isUsed(false), resnSlot(0) {}
    6465        };
    6566        typedef std::map< DeclarationWithType*, AssertionSetValue, AssertCompare > AssertionSet;
    6667        typedef std::map< std::string, TypeDecl::Data > OpenVarSet;
     68
     69        /// merges one set of open vars into another
     70        static inline void mergeOpenVars( OpenVarSet& dst, const OpenVarSet& src ) {
     71                for ( const auto& entry : src ) { dst[ entry.first ] = entry.second; }
     72        }
    6773
    6874        void printAssertionSet( const AssertionSet &, std::ostream &, int indent = 0 );
     
    9197
    9298        class TypeEnvironment {
     99                using ClassList = std::list< EqvClass >;
    93100          public:
    94101                const EqvClass* lookup( const std::string &var ) const;
     
    103110                bool isEmpty() const { return env.empty(); }
    104111                void print( std::ostream &os, Indenter indent = {} ) const;
    105                 // void combine( const TypeEnvironment &second, Type *(*combineFunc)( Type*, Type* ) );
     112               
     113                /// Simply concatenate the second environment onto this one; no safety checks performed
    106114                void simpleCombine( const TypeEnvironment &second );
     115
     116          private:
     117                /// Unifies the type bound of to with the type bound of from, returning false if fails
     118                bool mergeBound( EqvClass& to, const EqvClass& from, OpenVarSet& openVars, const SymTab::Indexer& indexer );
     119
     120                /// Merges two type classes from local environment, returning false if fails
     121                bool mergeClasses( ClassList::iterator to, ClassList::iterator from, OpenVarSet& openVars, const SymTab::Indexer& indexer );
     122
     123          public:
     124                /// Merges the second environment with this one, checking compatibility.
     125                /// Returns false if fails, but does NOT roll back partial changes.
     126                bool combine( const TypeEnvironment& second, OpenVarSet& openVars, const SymTab::Indexer& indexer );
     127               
    107128                void extractOpenVars( OpenVarSet &openVars ) const;
    108129                TypeEnvironment *clone() const { return new TypeEnvironment( *this ); }
     
    123144                void forbidWidening();
    124145
    125                 using iterator = std::list< EqvClass >::const_iterator;
     146                using iterator = ClassList::const_iterator;
    126147                iterator begin() const { return env.begin(); }
    127148                iterator end() const { return env.end(); }
    128149
    129150          private:
    130                 std::list< EqvClass > env;
     151                ClassList env;
    131152               
    132                 std::list< EqvClass >::iterator internal_lookup( const std::string &var );
     153                ClassList::iterator internal_lookup( const std::string &var );
    133154        };
    134155
  • src/ResolvExpr/module.mk

    r9b086ca rcde3891  
    3333       ResolvExpr/TypeEnvironment.cc \
    3434       ResolvExpr/CurrentObject.cc \
    35        ResolvExpr/ExplodedActual.cc
     35       ResolvExpr/ExplodedActual.cc \
     36       ResolvExpr/SpecCost.cc \
     37       ResolvExpr/ResolveAssertions.cc
  • src/ResolvExpr/typeops.h

    r9b086ca rcde3891  
    7272        Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );
    7373
     74        // in AlternativeFinder.cc
     75        Cost computeConversionCost( Type *actualType, Type *formalType,
     76                const SymTab::Indexer &indexer, const TypeEnvironment &env );
     77
    7478        // in PtrsAssignable.cc
    7579        int ptrsAssignable( Type *src, Type *dest, const TypeEnvironment &env );
     
    102106        int polyCost( Type *type, const TypeEnvironment &env, const SymTab::Indexer &indexer );
    103107
     108        // in SpecCost.cc
     109        int specCost( Type *type );
     110
    104111        // in Occurs.cc
    105112        bool occurs( Type *type, std::string varName, const TypeEnvironment &env );
     113
     114        template<typename Iter>
     115        bool occursIn( Type* ty, Iter begin, Iter end, const TypeEnvironment &env ) {
     116                while ( begin != end ) {
     117                        if ( occurs( ty, *begin, env ) ) return true;
     118                        ++begin;
     119                }
     120                return false;
     121        }
    106122
    107123        // in AlternativeFinder.cc
  • src/SymTab/Demangle.cc

    r9b086ca rcde3891  
    392392                                parsers.emplace_back(Encoding::enum_t, [this](Type::Qualifiers tq) { return parseEnum(tq); });
    393393                                parsers.emplace_back(Encoding::type, [this](Type::Qualifiers tq) { return parseType(tq); });
    394                                 parsers.emplace_back(Encoding::zero, [this](Type::Qualifiers tq) { return new ZeroType(tq); });
    395                                 parsers.emplace_back(Encoding::one, [this](Type::Qualifiers tq) { return new OneType(tq); });
     394                                parsers.emplace_back(Encoding::zero, [](Type::Qualifiers tq) { return new ZeroType(tq); });
     395                                parsers.emplace_back(Encoding::one, [](Type::Qualifiers tq) { return new OneType(tq); });
    396396                        }
    397397
  • src/SymTab/Mangler.cc

    r9b086ca rcde3891  
    1515#include "Mangler.h"
    1616
    17 #include <algorithm>                // for copy, transform
    18 #include <cassert>                  // for assert, assertf
    19 #include <functional>               // for const_mem_fun_t, mem_fun
    20 #include <iterator>                 // for ostream_iterator, back_insert_ite...
    21 #include <list>                     // for _List_iterator, list, _List_const...
    22 #include <string>                   // for string, char_traits, operator<<
    23 
    24 #include "CodeGen/OperatorTable.h"  // for OperatorInfo, operatorLookup
     17#include <algorithm>                     // for copy, transform
     18#include <cassert>                       // for assert, assertf
     19#include <functional>                    // for const_mem_fun_t, mem_fun
     20#include <iterator>                      // for ostream_iterator, back_insert_ite...
     21#include <list>                          // for _List_iterator, list, _List_const...
     22#include <string>                        // for string, char_traits, operator<<
     23
     24#include "CodeGen/OperatorTable.h"       // for OperatorInfo, operatorLookup
    2525#include "Common/PassVisitor.h"
    26 #include "Common/SemanticError.h"   // for SemanticError
    27 #include "Common/utility.h"         // for toString
    28 #include "Parser/LinkageSpec.h"     // for Spec, isOverridable, AutoGen, Int...
    29 #include "SynTree/Declaration.h"    // for TypeDecl, DeclarationWithType
    30 #include "SynTree/Expression.h"     // for TypeExpr, Expression, operator<<
    31 #include "SynTree/Type.h"           // for Type, ReferenceToType, Type::Fora...
     26#include "Common/SemanticError.h"        // for SemanticError
     27#include "Common/utility.h"              // for toString
     28#include "Parser/LinkageSpec.h"          // for Spec, isOverridable, AutoGen, Int...
     29#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
     30#include "SynTree/Declaration.h"         // for TypeDecl, DeclarationWithType
     31#include "SynTree/Expression.h"          // for TypeExpr, Expression, operator<<
     32#include "SynTree/Type.h"                // for Type, ReferenceToType, Type::Fora...
    3233
    3334namespace SymTab {
     
    3738                        struct Mangler : public WithShortCircuiting, public WithVisitorRef<Mangler>, public WithGuards {
    3839                                Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams );
     40                                Mangler( const ResolvExpr::TypeEnvironment& env );
    3941                                Mangler( const Mangler & ) = delete;
    4042
     
    6567                          private:
    6668                                std::ostringstream mangleName;  ///< Mangled name being constructed
    67                                 typedef std::map< std::string, std::pair< int, int > > VarMapType;
     69                                typedef std::map< std::string, std::pair< std::string, int > > VarMapType;
    6870                                VarMapType varNums;             ///< Map of type variables to indices
    6971                                int nextVarNum;                 ///< Next type variable index
     72                                const ResolvExpr::TypeEnvironment* env;  ///< optional environment for substitutions
    7073                                bool isTopLevel;                ///< Is the Mangler at the top level
    7174                                bool mangleOverridable;         ///< Specially mangle overridable built-in methods
     
    7578                                bool inQualifiedType = false;   ///< Add start/end delimiters around qualified type
    7679
     80                          public:
     81                                Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
     82                                        int nextVarNum, const ResolvExpr::TypeEnvironment* env,
     83                                        const VarMapType& varNums );
     84
     85                          private:
    7786                                void mangleDecl( DeclarationWithType *declaration );
    7887                                void mangleRef( ReferenceToType *refType, std::string prefix );
     
    100109                }
    101110
     111                std::string mangleAssnKey( DeclarationWithType* decl,
     112                                const ResolvExpr::TypeEnvironment& env ) {
     113                        PassVisitor<Mangler> mangler( env );
     114                        maybeAccept( decl, mangler );
     115                        return mangler.pass.get_mangleName();
     116                }
     117
    102118                namespace {
    103119                        Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams )
    104                                 : nextVarNum( 0 ), isTopLevel( true ), mangleOverridable( mangleOverridable ), typeMode( typeMode ), mangleGenericParams( mangleGenericParams ) {}
     120                                : nextVarNum( 0 ), env(nullptr), isTopLevel( true ),
     121                                mangleOverridable( mangleOverridable ), typeMode( typeMode ),
     122                                mangleGenericParams( mangleGenericParams ) {}
     123                       
     124                        Mangler::Mangler( const ResolvExpr::TypeEnvironment& env )
     125                                : nextVarNum( 0 ), env( &env ), isTopLevel( true ), mangleOverridable( false ),
     126                                typeMode( false ), mangleGenericParams( true ) {}
     127                       
     128                        Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
     129                                int nextVarNum, const ResolvExpr::TypeEnvironment* env,
     130                                const VarMapType& varNums )
     131                                : varNums( varNums ), nextVarNum( nextVarNum ), env( env ), isTopLevel( false ),
     132                                mangleOverridable( mangleOverridable ), typeMode( typeMode ),
     133                                mangleGenericParams( mangleGenericParams ) {}
    105134
    106135                        void Mangler::mangleDecl( DeclarationWithType * declaration ) {
     
    329358                                                        assert( false );
    330359                                                } // switch
    331                                                 varNums[ (*i)->name ] = std::pair< int, int >( nextVarNum++, (int)(*i)->get_kind() );
     360                                                std::string varName;
     361                                                // replace type with substitution name if environment is available and bound
     362                                                if ( env ) {
     363                                                        const ResolvExpr::EqvClass* varClass = env->lookup( (*i)->name );
     364                                                        if ( varClass && varClass->type ) {
     365                                                                PassVisitor<Mangler> sub_mangler(
     366                                                                        mangleOverridable, typeMode, mangleGenericParams, nextVarNum,
     367                                                                        env, varNums );
     368                                                                varClass->type->accept( sub_mangler );
     369                                                                varName = std::string{"%"} + sub_mangler.pass.get_mangleName();
     370                                                        }
     371                                                }
     372                                                // otherwise just give type numeric name
     373                                                if ( varName.empty() ) {
     374                                                        varName = std::to_string( nextVarNum++ );
     375                                                }
     376                                                varNums[ (*i)->name ] = std::make_pair( varName, (int)(*i)->get_kind() );
    332377                                                for ( std::list< DeclarationWithType* >::iterator assert = (*i)->assertions.begin(); assert != (*i)->assertions.end(); ++assert ) {
    333                                                         PassVisitor<Mangler> sub_mangler( mangleOverridable, typeMode, mangleGenericParams );
    334                                                         sub_mangler.pass.nextVarNum = nextVarNum;
    335                                                         sub_mangler.pass.isTopLevel = false;
    336                                                         sub_mangler.pass.varNums = varNums;
     378                                                        PassVisitor<Mangler> sub_mangler(
     379                                                                mangleOverridable, typeMode, mangleGenericParams, nextVarNum, env,
     380                                                                varNums );
    337381                                                        (*assert)->accept( sub_mangler );
    338                                                         assertionNames.push_back( sub_mangler.pass.mangleName.str() );
     382                                                        assertionNames.push_back( sub_mangler.pass.get_mangleName() );
    339383                                                        acount++;
    340384                                                } // for
  • src/SymTab/Mangler.h

    r9b086ca rcde3891  
    3131// * Currently name compression is not implemented.
    3232
     33namespace ResolvExpr {
     34        class TypeEnvironment;
     35}
     36
    3337namespace SymTab {
    3438        namespace Mangler {
     
    4044                /// Mangle ignoring generic type parameters
    4145                std::string mangleConcrete( Type* ty );
     46                /// Mangle for assertion key
     47                std::string mangleAssnKey( DeclarationWithType* decl,
     48                        const ResolvExpr::TypeEnvironment& env );
    4249
    4350                namespace Encoding {
  • src/SymTab/Validate.cc

    r9b086ca rcde3891  
    398398                        assert( aggr ); // TODO: need to handle forward declarations
    399399                        for ( Declaration * member : aggr->members ) {
    400                                 if ( StructInstType * inst = dynamic_cast< StructInstType * >( child ) ) {
    401                                         if ( StructDecl * aggr = dynamic_cast< StructDecl * >( member ) ) {
    402                                                 if ( aggr->name == inst->name ) {
    403                                                         // TODO: is this case, and other non-TypeInstType cases, necessary?
    404                                                         return new StructInstType( qualType->get_qualifiers(), aggr );
    405                                                 }
    406                                         }
    407                                 } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( child ) ) {
    408                                         if ( UnionDecl * aggr = dynamic_cast< UnionDecl * > ( member ) ) {
    409                                                 if ( aggr->name == inst->name ) {
    410                                                         return new UnionInstType( qualType->get_qualifiers(), aggr );
    411                                                 }
    412                                         }
    413                                 } else if ( EnumInstType * inst = dynamic_cast< EnumInstType * >( child ) ) {
    414                                         if ( EnumDecl * aggr = dynamic_cast< EnumDecl * > ( member ) ) {
    415                                                 if ( aggr->name == inst->name ) {
    416                                                         return new EnumInstType( qualType->get_qualifiers(), aggr );
    417                                                 }
    418                                         }
    419                                 } else if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( child ) ) {
     400                                if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( child ) ) {
    420401                                        // name on the right is a typedef
    421402                                        if ( NamedTypeDecl * aggr = dynamic_cast< NamedTypeDecl * > ( member ) ) {
     
    424405                                                        Type * ret = aggr->base->clone();
    425406                                                        ret->get_qualifiers() = qualType->get_qualifiers();
     407                                                        TypeSubstitution sub = parent->genericSubstitution();
     408                                                        sub.apply(ret);
    426409                                                        return ret;
    427410                                                }
  • src/SynTree/ApplicationExpr.cc

    r9b086ca rcde3891  
    2929
    3030ParamEntry::ParamEntry( const ParamEntry &other ) :
    31                 decl( other.decl ), actualType( maybeClone( other.actualType ) ), formalType( maybeClone( other.formalType ) ), expr( maybeClone( other.expr ) ), inferParams( new InferredParams( *other.inferParams ) ) {
     31                decl( other.decl ), actualType( maybeClone( other.actualType ) ), formalType( maybeClone( other.formalType ) ), expr( maybeClone( other.expr ) )/*, inferParams( new InferredParams( *other.inferParams ) )*/ {
    3232}
    3333
     
    3939        formalType = maybeClone( other.formalType );
    4040        expr = maybeClone( other.expr );
    41         *inferParams = *other.inferParams;
     41        // *inferParams = *other.inferParams;
    4242        return *this;
    4343}
     
    5050
    5151ParamEntry::ParamEntry( ParamEntry && other ) :
    52                 decl( other.decl ), actualType( other.actualType ), formalType( other.formalType ), expr( other.expr ), inferParams( std::move( other.inferParams ) ) {
     52                decl( other.decl ), actualType( other.actualType ), formalType( other.formalType ), expr( other.expr )/*, inferParams( std::move( other.inferParams ) )*/ {
    5353        other.actualType = nullptr;
    5454        other.formalType = nullptr;
     
    6868        other.formalType = nullptr;
    6969        other.expr = nullptr;
    70         inferParams = std::move( other.inferParams );
     70        // inferParams = std::move( other.inferParams );
    7171        return *this;
    7272}
  • src/SynTree/Constant.cc

    r9b086ca rcde3891  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jul 14 14:50:00 2017
    13 // Update Count     : 29
     12// Last Modified On : Fri Spt 28 14:49:00 2018
     13// Update Count     : 30
    1414//
    1515
     
    1919
    2020#include "Constant.h"
     21#include "Expression.h" // for ConstantExpr
    2122#include "Type.h"    // for BasicType, Type, Type::Qualifiers, PointerType
    2223
     
    4849Constant Constant::from_double( double d ) {
    4950        return Constant( new BasicType( Type::Qualifiers(), BasicType::Double ), std::to_string( d ), d );
     51}
     52
     53Constant Constant::from_string( std::string const & str ) {
     54        return Constant(
     55                new ArrayType(
     56                        noQualifiers,
     57                        new BasicType( Type::Qualifiers( Type::Const ), BasicType::Char ),
     58                        new ConstantExpr( Constant::from_int( str.size() + 1 /* \0 */ )),
     59                        false, false ),
     60                std::string("\"") + str + "\"", (unsigned long long int)0 );
    5061}
    5162
  • src/SynTree/Constant.h

    r9b086ca rcde3891  
    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 : Sat Jul 22 09:54:46 2017
    13 // Update Count     : 17
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Spt 28 14:48:00 2018
     13// Update Count     : 18
    1414//
    1515
     
    5151        /// generates a floating point constant of the given double
    5252        static Constant from_double( double d );
     53        /// generates an array of chars constant of the given string
     54        static Constant from_string( std::string const & s );
    5355
    5456        /// generates a null pointer value for the given type. void * if omitted.
  • src/SynTree/Expression.cc

    r9b086ca rcde3891  
    4040                        Declaration::declFromId( i->second.decl )->printShort( os, indent+1 );
    4141                        os << std::endl;
    42                         printInferParams( *i->second.inferParams, os, indent+1, level+1 );
     42                        printInferParams( i->second.expr->inferParams, os, indent+1, level+1 );
    4343                } // for
    4444        } // if
     
    4747Expression::Expression() : result( 0 ), env( 0 ) {}
    4848
    49 Expression::Expression( const Expression &other ) : BaseSyntaxNode( other ), result( maybeClone( other.result ) ), env( maybeClone( other.env ) ), extension( other.extension ), inferParams( other.inferParams ) {
    50 }
     49Expression::Expression( const Expression &other ) : BaseSyntaxNode( other ), result( maybeClone( other.result ) ), env( maybeClone( other.env ) ), extension( other.extension ), inferParams( other.inferParams ), resnSlots( other.resnSlots ) {}
    5150
    5251void Expression::spliceInferParams( Expression * other ) {
     
    5554                inferParams[p.first] = std::move( p.second );
    5655        }
     56        resnSlots.insert( resnSlots.end(), other->resnSlots.begin(), other->resnSlots.end() );
    5757}
    5858
     
    376376        os << "Untyped Member Expression, with field: " << std::endl << indent+1;
    377377        member->print(os, indent+1 );
    378         os << indent << "... from aggregate: " << std::endl << indent+1;
     378        os << indent << "... from aggregate:" << std::endl << indent+1;
    379379        aggregate->print(os, indent+1);
    380380        Expression::print( os, indent );
     
    405405
    406406void MemberExpr::print( std::ostream &os, Indenter indent ) const {
    407         os << "Member Expression, with field: " << std::endl;
     407        os << "Member Expression, with field:" << std::endl;
    408408        os << indent+1;
    409409        member->print( os, indent+1 );
    410         os << std::endl << indent << "... from aggregate: " << std::endl << indent+1;
     410        os << std::endl << indent << "... from aggregate:" << std::endl << indent+1;
    411411        aggregate->print(os, indent + 1);
    412412        Expression::print( os, indent );
     
    456456
    457457void UntypedExpr::print( std::ostream &os, Indenter indent ) const {
    458         os << "Applying untyped: " << std::endl;
     458        os << "Applying untyped:" << std::endl;
    459459        os << indent+1;
    460460        function->print(os, indent+1);
    461         os << std::endl << indent << "...to: " << std::endl;
     461        os << std::endl << indent << "...to:" << std::endl;
    462462        printAll(args, os, indent+1);
    463463        Expression::print( os, indent );
  • src/SynTree/Expression.h

    r9b086ca rcde3891  
    2121#include <memory>                 // for allocator, unique_ptr
    2222#include <string>                 // for string
     23#include <vector>                 // for vector
    2324
    2425#include "BaseSyntaxNode.h"       // for BaseSyntaxNode
     
    3839/// but subject to decay-to-pointer and type parameter renaming
    3940struct ParamEntry {
    40         ParamEntry(): decl( 0 ), actualType( 0 ), formalType( 0 ), expr( 0 ), inferParams( new InferredParams ) {}
    41         ParamEntry( UniqueId decl, Type * actualType, Type * formalType, Expression* expr ): decl( decl ), actualType( actualType ), formalType( formalType ), expr( expr ), inferParams( new InferredParams ) {}
     41        ParamEntry(): decl( 0 ), actualType( 0 ), formalType( 0 ), expr( 0 )/*, inferParams( new InferredParams )*/ {}
     42        ParamEntry( UniqueId decl, Type * actualType, Type * formalType, Expression* expr ): decl( decl ), actualType( actualType ), formalType( formalType ), expr( expr )/*, inferParams( new InferredParams )*/ {}
    4243        ParamEntry( const ParamEntry & other );
    4344        ParamEntry( ParamEntry && other );
     
    5051        Type * formalType;
    5152        Expression * expr;
    52         std::unique_ptr< InferredParams > inferParams;
     53        // std::unique_ptr< InferredParams > inferParams;
    5354};
    5455
     
    5960        TypeSubstitution * env;
    6061        bool extension = false;
    61         InferredParams inferParams;
     62        InferredParams inferParams;       ///< Post-resolution inferred parameter slots
     63        std::vector<UniqueId> resnSlots;  ///< Pre-resolution inferred parameter slots
     64       
     65        // xxx - should turn inferParams+resnSlots into a union to save some memory
    6266
    6367        Expression();
     
    7377        bool get_extension() const { return extension; }
    7478        Expression * set_extension( bool exten ) { extension = exten; return this; }
    75 
    76         InferredParams & get_inferParams() { return inferParams; }
    7779
    7880        // move other's inferParams to this
  • src/SynTree/FunctionDecl.cc

    r9b086ca rcde3891  
    8787
    8888        if ( statements ) {
    89                 os << indent << "... with body " << endl << indent+1;
     89                os << indent << "... with body" << endl << indent+1;
    9090                statements->print( os, indent+1 );
    9191        } // if
  • src/SynTree/FunctionType.cc

    r9b086ca rcde3891  
    6666                os << indent+1 << "accepting unspecified arguments" << endl;
    6767        } // if
    68         os << indent << "... returning ";
     68        os << indent << "... returning";
    6969        if ( returnVals.empty() ) {
    70                 os << "nothing " << endl;
     70                os << " nothing" << endl;
    7171        } else {
    7272                os << endl;
  • src/SynTree/ObjectDecl.cc

    r9b086ca rcde3891  
    6666
    6767        if ( ! attributes.empty() ) {
    68                 os << std::endl << indent << "... with attributes: " << std::endl;
     68                os << std::endl << indent << "... with attributes:" << std::endl;
    6969                printAll( attributes, os, indent+1 );
    7070        }
  • src/SynTree/ReferenceToType.cc

    r9b086ca rcde3891  
    9393        else {
    9494                Type::print( os, indent );
    95                 os << "instance of " << typeString() << " " << name << " with body " << baseStruct->has_body() << " ";
     95                os << "instance of " << typeString() << " " << name << " with body " << baseStruct->has_body();
    9696                if ( ! parameters.empty() ) {
    9797                        os << endl << indent << "... with parameters" << endl;
     
    136136        else {
    137137                Type::print( os, indent );
    138                 os << "instance of " << typeString() << " " << name << " with body " << baseUnion->has_body() << " ";
     138                os << "instance of " << typeString() << " " << name << " with body " << baseUnion->has_body();
    139139                if ( ! parameters.empty() ) {
    140140                        os << endl << indent << "... with parameters" << endl;
     
    160160        else {
    161161                Type::print( os, indent );
    162                 os << "instance of " << typeString() << " " << name << " with body " << baseEnum->has_body() << " ";
     162                os << "instance of " << typeString() << " " << name << " with body " << baseEnum->has_body();
    163163        } // if
    164164}
     
    205205
    206206        Type::print( os, indent );
    207         os << "instance of " << typeString() << " " << get_name() << " (" << ( isFtype ? "" : "not" ) << " function type) ";
     207        os << "instance of " << typeString() << " " << get_name() << " (" << ( isFtype ? "" : "not" ) << " function type)";
    208208        if ( ! parameters.empty() ) {
    209209                os << endl << indent << "... with parameters" << endl;
  • src/SynTree/Type.cc

    r9b086ca rcde3891  
    118118
    119119void QualifiedType::print( std::ostream & os, Indenter indent ) const {
    120         os << "Qualified Type: " << endl;
     120        os << "Qualified Type:" << endl;
    121121        os << indent+1;
    122122        parent->print( os, indent+1 );
  • src/SynTree/Type.h

    r9b086ca rcde3891  
    598598class TypeofType : public Type {
    599599  public:
    600         Expression *expr;
    601 
    602         TypeofType( const Type::Qualifiers & tq, Expression *expr, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
     600        Expression *expr;    ///< expression to take the type of
     601        bool is_basetypeof;  ///< true iff is basetypeof type
     602
     603        TypeofType( const Type::Qualifiers & tq, Expression *expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     604        TypeofType( const Type::Qualifiers & tq, Expression *expr, bool is_basetypeof,
     605                const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    603606        TypeofType( const TypeofType& );
    604607        virtual ~TypeofType();
  • src/SynTree/TypeofType.cc

    r9b086ca rcde3891  
    2323class Attribute;
    2424
    25 TypeofType::TypeofType( const Type::Qualifiers &tq, Expression *expr, const std::list< Attribute * > & attributes ) : Type( tq, attributes ), expr( expr ) {
    26 }
     25TypeofType::TypeofType( const Type::Qualifiers &tq, Expression *expr,
     26        const std::list< Attribute * > & attributes )
     27: Type( tq, attributes ), expr( expr ), is_basetypeof(false) {}
    2728
    28 TypeofType::TypeofType( const TypeofType &other ) : Type( other ), expr( maybeClone( other.expr ) ) {
    29 }
     29TypeofType::TypeofType( const Type::Qualifiers &tq, Expression *expr, bool is_basetypeof,
     30        const std::list< Attribute * > & attributes )
     31: Type( tq, attributes ), expr( expr ), is_basetypeof( is_basetypeof ) {}
     32
     33TypeofType::TypeofType( const TypeofType &other )
     34: Type( other ), expr( maybeClone( other.expr ) ), is_basetypeof( other.is_basetypeof ) {}
    3035
    3136TypeofType::~TypeofType() {
     
    3540void TypeofType::print( std::ostream &os, Indenter indent ) const {
    3641        Type::print( os, indent );
     42        if ( is_basetypeof ) { os << "base-"; }
    3743        os << "type-of expression ";
    3844        if ( expr ) {
  • src/Tuples/Explode.h

    r9b086ca rcde3891  
    4444        template<typename OutputIterator>
    4545        void append( OutputIterator out, Expression* expr, const ResolvExpr::TypeEnvironment& env,
     46                        const ResolvExpr::OpenVarSet& openVars, const ResolvExpr::AssertionList& need,
    4647                        const ResolvExpr::Cost& cost, const ResolvExpr::Cost& cvtCost ) {
    47                 *out++ = ResolvExpr::Alternative{ expr, env, cost, cvtCost };
     48                *out++ = ResolvExpr::Alternative{ expr, env, openVars, need, cost, cvtCost };
    4849        }
    4950
    5051        /// Append alternative to an ExplodedActual
    5152        static inline void append( ResolvExpr::ExplodedActual& ea, Expression* expr,
    52                         const ResolvExpr::TypeEnvironment&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) {
     53                        const ResolvExpr::TypeEnvironment&, const ResolvExpr::OpenVarSet&,
     54                        const ResolvExpr::AssertionList&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) {
    5355                ea.exprs.emplace_back( expr );
    54                 /// xxx -- merge environment, cost?
     56                /// xxx -- merge environment, openVars, need, cost?
    5557        }
    5658
     
    6870                                        // distribute reference cast over all components
    6971                                        append( std::forward<Output>(out), distributeReference( alt.release_expr() ),
    70                                                 alt.env, alt.cost, alt.cvtCost );
     72                                                alt.env, alt.openVars, alt.need, alt.cost, alt.cvtCost );
    7173                                }
    7274                                // in tuple assignment, still need to handle the other cases, but only if not already handled here (don't want to output too many alternatives)
     
    102104                } else {
    103105                        // atomic (non-tuple) type - output a clone of the expression in a new alternative
    104                         append( std::forward<Output>(out), expr->clone(), alt.env, alt.cost, alt.cvtCost );
     106                        append( std::forward<Output>(out), expr->clone(), alt.env, alt.openVars, alt.need, 
     107                                alt.cost, alt.cvtCost );
    105108                }
    106109        }
  • src/Tuples/TupleAssignment.cc

    r9b086ca rcde3891  
    6262                struct Matcher {
    6363                  public:
    64                         Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, const
    65                                 ResolvExpr::AltList& rhs );
     64                        Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs,
     65                                const ResolvExpr::AltList& rhs );
    6666                        virtual ~Matcher() {}
     67                       
    6768                        virtual void match( std::list< Expression * > &out ) = 0;
    6869                        ObjectDecl * newObject( UniqueName & namer, Expression * expr );
     70
     71                        void combineState( const ResolvExpr::Alternative& alt ) {
     72                                compositeEnv.simpleCombine( alt.env );
     73                                ResolvExpr::mergeOpenVars( openVars, alt.openVars );
     74                                cloneAll( alt.need, need );
     75                        }
     76
     77                        void combineState( const ResolvExpr::AltList& alts ) {
     78                                for ( const ResolvExpr::Alternative& alt : alts ) { combineState( alt ); }
     79                        }
     80                       
    6981                        ResolvExpr::AltList lhs, rhs;
    7082                        TupleAssignSpotter &spotter;
     
    7284                        std::list< ObjectDecl * > tmpDecls;
    7385                        ResolvExpr::TypeEnvironment compositeEnv;
     86                        ResolvExpr::OpenVarSet openVars;
     87                        ResolvExpr::AssertionSet need;
    7488                };
    7589
     
    245259                }
    246260
    247                 // extract expressions from the assignment alternatives to produce a list of assignments that
    248                 // together form a single alternative
     261                // extract expressions from the assignment alternatives to produce a list of assignments
     262                // that together form a single alternative
    249263                std::list< Expression *> solved_assigns;
    250264                for ( ResolvExpr::Alternative & alt : current ) {
    251265                        solved_assigns.push_back( alt.expr->clone() );
    252                 }
    253                 // combine assignment environments into combined expression environment
    254                 simpleCombineEnvironments( current.begin(), current.end(), matcher->compositeEnv );
     266                        matcher->combineState( alt );
     267                }
     268               
    255269                // xxx -- was push_front
    256                 currentFinder.get_alternatives().push_back( ResolvExpr::Alternative(
    257                         new TupleAssignExpr(solved_assigns, matcher->tmpDecls), matcher->compositeEnv,
    258                         ResolvExpr::sumCost( current ) + matcher->baseCost ) );
     270                currentFinder.get_alternatives().push_back( ResolvExpr::Alternative{
     271                        new TupleAssignExpr{ solved_assigns, matcher->tmpDecls }, matcher->compositeEnv,
     272                        matcher->openVars,
     273                        ResolvExpr::AssertionList( matcher->need.begin(), matcher->need.end() ),
     274                        ResolvExpr::sumCost( current ) + matcher->baseCost } );
    259275        }
    260276
     
    263279        : lhs(lhs), rhs(rhs), spotter(spotter),
    264280          baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ) {
    265                 simpleCombineEnvironments( lhs.begin(), lhs.end(), compositeEnv );
    266                 simpleCombineEnvironments( rhs.begin(), rhs.end(), compositeEnv );
     281                combineState( lhs );
     282                combineState( rhs );
    267283        }
    268284
  • src/cfa.make

    r9b086ca rcde3891  
     1
     2
    13CFACOMPILE = $(CFACC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CFAFLAGS) $(CFAFLAGS) $(AM_CFLAGS) $(CFLAGS)
     4LTCFACOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
     5        $(LIBTOOLFLAGS) --mode=compile $(CFACC) $(DEFS) \
     6        $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CFAFLAGS) $(CFAFLAGS) \
     7        $(AM_CFLAGS) $(CFLAGS)
    28
    39AM_V_CFA = $(am__v_CFA_@AM_V@)
     
    612am__v_CFA_1 =
    713
    8 .cfa.o: $(CFACC) $(CFACPP)
     14.cfa.o:
    915        $(AM_V_CFA)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
    1016        $(CFACOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
    1117        $(am__mv) $$depbase.Tpo $$depbase.Po
     18
     19.cfa.lo:
     20        $(AM_V_CFA)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
     21        $(LTCFACOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
     22        $(am__mv) $$depbase.Tpo $$depbase.Plo
     23
     24AM_V_JAVAC = $(am__v_JAVAC_@AM_V@)
     25am__v_JAVAC_ = $(am__v_JAVAC_@AM_DEFAULT_V@)
     26am__v_JAVAC_0 = @echo "  JAVAC   " $@;
     27am__v_JAVAC_1 =
     28
     29AM_V_GOC = $(am__v_GOC_@AM_V@)
     30am__v_GOC_ = $(am__v_GOC_@AM_DEFAULT_V@)
     31am__v_GOC_0 = @echo "  GOC     " $@;
     32am__v_GOC_1 =
     33
     34UPPCC = u++
     35UPPCOMPILE = $(UPPCC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_UPPFLAGS) $(UPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_CFLAGS) $(CFLAGS)
     36
     37AM_V_UPP = $(am__v_UPP_@AM_V@)
     38am__v_UPP_ = $(am__v_UPP_@AM_DEFAULT_V@)
     39am__v_UPP_0 = @echo "  UPP     " $@;
     40am__v_UPP_1 =
  • src/config.h.in

    r9b086ca rcde3891  
    77#undef CFA_64_CPU
    88
    9 /* Location of include files. */
     9/* Backend compiler to use. */
    1010#undef CFA_BACKEND_CC
    1111
     
    6767#undef HAVE_ALLOCA_H
    6868
     69/* Define to 1 if you have the <dlfcn.h> header file. */
     70#undef HAVE_DLFCN_H
     71
    6972/* Define to 1 if you have the <fenv.h> header file. */
    7073#undef HAVE_FENV_H
     
    129132/* Define to 1 if the system has the type `_Bool'. */
    130133#undef HAVE__BOOL
     134
     135/* Define to the sub-directory where libtool stores uninstalled libraries. */
     136#undef LT_OBJDIR
    131137
    132138/* Name of package */
  • src/main.cc

    r9b086ca rcde3891  
    1010// Created On       : Fri May 15 23:12:02 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jun  6 15:51:47 2018
    13 // Update Count     : 498
     12// Last Modified On : Wed Dec 26 08:11:19 2018
     13// Update Count     : 499
    1414//
    1515
     
    3434#include "CodeGen/Generate.h"               // for generate
    3535#include "CodeTools/DeclStats.h"            // for printDeclStats
     36#include "CodeTools/ResolvProtoDump.h"      // for dumpAsResolvProto
    3637#include "CodeTools/TrackLoc.h"             // for fillLocations
    3738#include "Common/CompilerError.h"           // for CompilerError
     
    171172                        if ( filename == nullptr ) filename = argv[ optind ];
    172173                        // prelude filename comes in differently
    173                         if ( libcfap ) filename = "prelude.cf";
     174                        if ( libcfap ) filename = "prelude.cfa";
    174175                        optind += 1;
    175176                } else {                                                                                // no input file name
     
    198199                        if ( ! libcfap ) {
    199200                                // read the prelude in, if not generating the cfa library
    200                                 FILE * prelude = fopen( (PreludeDirector + "/prelude.cf").c_str(), "r" );
    201                                 assertf( prelude, "cannot open prelude.cf\n" );
     201                                FILE * prelude = fopen( (PreludeDirector + "/prelude.cfa").c_str(), "r" );
     202                                assertf( prelude, "cannot open prelude.cfa\n" );
    202203                                parse( prelude, LinkageSpec::Intrinsic );
    203204
     
    270271
    271272                CodeTools::fillLocations( translationUnit );
     273
     274                if ( resolvprotop ) {
     275                        CodeTools::dumpAsResolvProto( translationUnit );
     276                        return 0;
     277                }
    272278
    273279                PASS( "resolve", ResolvExpr::resolve( translationUnit ) );
     
    365371                        }
    366372                } catch(const std::exception& e) {
    367                         std::cerr << "Unaught Exception \"" << e.what() << "\"\n";
     373                        std::cerr << "Uncaught Exception \"" << e.what() << "\"\n";
    368374                }
    369375                return 1;
     
    376382
    377383void parse_cmdline( int argc, char * argv[], const char *& filename ) {
    378         enum { Ast, Bbox, Bresolver, CtorInitFix, DeclStats, Expr, ExprAlt, Grammar, LibCFA, Linemarks, Nolinemarks, Nopreamble, Parse, PreludeDir, Prototypes, Resolver, Symbol, Tree, TupleExpansion, Validate, };
     384        enum { Ast, Bbox, Bresolver, CtorInitFix, DeclStats, Expr, ExprAlt, Grammar, LibCFA, Linemarks, Nolinemarks, Nopreamble, Parse, PreludeDir, Prototypes, Resolver, ResolvProto, Symbol, Tree, TupleExpansion, Validate, };
    379385
    380386        static struct option long_opts[] = {
     
    395401                { "no-prototypes", no_argument, 0, Prototypes },
    396402                { "resolver", no_argument, 0, Resolver },
     403                { "resolv-proto", no_argument, 0, ResolvProto },
    397404                { "symbol", no_argument, 0, Symbol },
    398405                { "tree", no_argument, 0, Tree },
     
    407414        bool Wsuppress = false, Werror = false;
    408415        int c;
    409         while ( (c = getopt_long( argc, argv, "abBcCdefgGlLmnNpqrstTvwW:yzZD:F:", long_opts, &long_index )) != -1 ) {
     416        while ( (c = getopt_long( argc, argv, "abBcCdefgGlLmnNpqrRstTvwW:yzZD:F:", long_opts, &long_index )) != -1 ) {
    410417                switch ( c ) {
    411418                  case Ast:
     
    479486                  case 'r':                                                                             // print resolver steps
    480487                        resolvep = true;
     488                        break;
     489                  case 'R':                                                                             // dump resolv-proto instance
     490                        resolvprotop = true;
    481491                        break;
    482492                  case Symbol:
Note: See TracChangeset for help on using the changeset viewer.