Changeset c84dd61 for src


Ignore:
Timestamp:
Jun 21, 2023, 2:38:55 AM (2 years ago)
Author:
JiadaL <j82liang@…>
Branches:
master
Children:
92355883
Parents:
0b0a285 (diff), 2de175ce (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

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

Location:
src
Files:
32 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Convert.cpp

    r0b0a285 rc84dd61  
    23432343                                old->location,
    23442344                                GET_ACCEPT_1(arg, Expr),
    2345                                 old->isGenerated ? ast::GeneratedCast : ast::ExplicitCast
     2345                                old->isGenerated ? ast::GeneratedCast : ast::ExplicitCast,
     2346                                (ast::CastExpr::CastKind) old->kind
    23462347                        )
    23472348                );
  • src/AST/Expr.cpp

    r0b0a285 rc84dd61  
    186186// --- CastExpr
    187187
    188 CastExpr::CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g )
    189 : Expr( loc, new VoidType{} ), arg( a ), isGenerated( g ) {}
     188CastExpr::CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g, CastKind kind )
     189: Expr( loc, new VoidType{} ), arg( a ), isGenerated( g ), kind( kind ) {}
    190190
    191191bool CastExpr::get_lvalue() const {
  • src/AST/Expr.hpp

    r0b0a285 rc84dd61  
    5555                const Expr * e )
    5656        : decl( id ), declptr( declptr ), actualType( actual ), formalType( formal ), expr( e ) {}
     57
     58        operator bool() {return declptr;}
    5759};
    5860
     
    335337        GeneratedFlag isGenerated;
    336338
     339        enum CastKind {
     340                Default, // C
     341                Coerce, // reinterpret cast
     342                Return  // overload selection
     343        };
     344
     345        CastKind kind = Default;
     346
    337347        CastExpr( const CodeLocation & loc, const Expr * a, const Type * to,
    338                 GeneratedFlag g = GeneratedCast ) : Expr( loc, to ), arg( a ), isGenerated( g ) {}
     348                GeneratedFlag g = GeneratedCast, CastKind kind = Default ) : Expr( loc, to ), arg( a ), isGenerated( g ), kind( kind ) {}
    339349        /// Cast-to-void
    340         CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g = GeneratedCast );
     350        CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g = GeneratedCast, CastKind kind = Default );
    341351
    342352        /// Wrap a cast expression around an existing expression (always generated)
  • src/AST/SymbolTable.cpp

    r0b0a285 rc84dd61  
    1919
    2020#include "Copy.hpp"
     21#include <iostream>
     22#include <algorithm>
     23
    2124#include "Decl.hpp"
    2225#include "Expr.hpp"
     
    203206                        out.push_back(decl.second);
    204207                }
     208
     209                // std::cerr << otypeKey << ' ' << out.size() << std::endl;
    205210        }
    206211
  • src/AST/Type.hpp

    r0b0a285 rc84dd61  
    451451        bool operator==(const TypeEnvKey & other) const;
    452452        bool operator<(const TypeEnvKey & other) const;
    453 };
     453        operator bool() {return base;}
     454};
     455
    454456
    455457/// tuple type e.g. `[int, char]`
  • src/AST/TypeEnvironment.cpp

    r0b0a285 rc84dd61  
    135135                }
    136136        }
    137         sub.normalize();
     137        // sub.normalize();
    138138}
    139139
  • src/AST/TypeEnvironment.hpp

    r0b0a285 rc84dd61  
    6363
    6464                int cmp = d1->var->name.compare( d2->var->name );
    65                 return cmp < 0 || ( cmp == 0 && d1->result < d2->result );
     65                return cmp > 0 || ( cmp == 0 && d1->result < d2->result );
    6666        }
    6767};
  • src/Concurrency/Actors.cpp

    r0b0a285 rc84dd61  
    223223        if ( actorIter != actorStructDecls.end() && messageIter != messageStructDecls.end() ) {
    224224            //////////////////////////////////////////////////////////////////////
     225            // The following generates this wrapper for all receive(derived_actor &, derived_msg &) functions
     226            /* base_actor and base_msg are output params
     227            static inline allocation __CFA_receive_wrap( derived_actor & receiver, derived_msg & msg, actor ** base_actor, message ** base_msg ) {
     228                base_actor = &receiver;
     229                base_msg = &msg;
     230                return receive( receiver, msg );
     231            }
     232            */
     233            CompoundStmt * wrapBody = new CompoundStmt( decl->location );
     234
     235            // generates: base_actor = &receiver;
     236            wrapBody->push_back( new ExprStmt( decl->location,
     237                UntypedExpr::createAssign( decl->location,
     238                    UntypedExpr::createDeref( decl->location, new NameExpr( decl->location, "base_actor" ) ),
     239                    new AddressExpr( decl->location, new NameExpr( decl->location, "receiver" ) )
     240                )
     241            ));
     242
     243            // generates: base_msg = &msg;
     244            wrapBody->push_back( new ExprStmt( decl->location,
     245                UntypedExpr::createAssign( decl->location,
     246                    UntypedExpr::createDeref( decl->location, new NameExpr( decl->location, "base_msg" ) ),
     247                    new AddressExpr( decl->location, new NameExpr( decl->location, "msg" ) )
     248                )
     249            ));
     250
     251            // generates: return receive( receiver, msg );
     252            wrapBody->push_back( new ReturnStmt( decl->location,
     253                new UntypedExpr ( decl->location,
     254                    new NameExpr( decl->location, "receive" ),
     255                    {
     256                        new NameExpr( decl->location, "receiver" ),
     257                        new NameExpr( decl->location, "msg" )
     258                    }
     259                )
     260            ));
     261
     262            // create receive wrapper to extract base message and actor pointer
     263            // put it all together into the complete function decl from above
     264            FunctionDecl * receiveWrapper = new FunctionDecl(
     265                decl->location,
     266                "__CFA_receive_wrap",
     267                {},                     // forall
     268                {
     269                    new ObjectDecl(
     270                        decl->location,
     271                        "receiver",
     272                        ast::deepCopy( derivedActorRef )
     273                    ),
     274                    new ObjectDecl(
     275                        decl->location,
     276                        "msg",
     277                        ast::deepCopy( derivedMsgRef )
     278                    ),
     279                    new ObjectDecl(
     280                        decl->location,
     281                        "base_actor",
     282                        new PointerType( new PointerType( new StructInstType( *actorDecl ) ) )
     283                    ),
     284                    new ObjectDecl(
     285                        decl->location,
     286                        "base_msg",
     287                        new PointerType( new PointerType( new StructInstType( *msgDecl ) ) )
     288                    )
     289                },                      // params
     290                {
     291                    new ObjectDecl(
     292                        decl->location,
     293                        "__CFA_receive_wrap_ret",
     294                        new EnumInstType( *allocationDecl )
     295                    )
     296                },
     297                wrapBody,               // body
     298                { Storage::Static },    // storage
     299                Linkage::Cforall,       // linkage
     300                {},                     // attributes
     301                { Function::Inline }
     302            );
     303
     304            declsToAddAfter.push_back( receiveWrapper );
     305
     306            //////////////////////////////////////////////////////////////////////
    225307            // The following generates this send message operator routine for all receive(derived_actor &, derived_msg &) functions
    226308            /*
     
    246328            ));
    247329           
    248             // Function type is: allocation (*)( derived_actor &, derived_msg & )
     330            // Function type is: allocation (*)( derived_actor &, derived_msg &, actor **, message ** )
    249331            FunctionType * derivedReceive = new FunctionType();
    250332            derivedReceive->params.push_back( ast::deepCopy( derivedActorRef ) );
    251333            derivedReceive->params.push_back( ast::deepCopy( derivedMsgRef ) );
     334            derivedReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *actorDecl ) ) ) );
     335            derivedReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *msgDecl ) ) ) );
    252336            derivedReceive->returns.push_back( new EnumInstType( *allocationDecl ) );
    253337
    254             // Generates: allocation (*my_work_fn)( derived_actor &, derived_msg & ) = receive;
     338            // Generates: allocation (*my_work_fn)( derived_actor &, derived_msg &, actor **, message ** ) = receive;
    255339            sendBody->push_back( new DeclStmt(
    256340                decl->location,
     
    259343                    "my_work_fn",
    260344                    new PointerType( derivedReceive ),
    261                     new SingleInit( decl->location, new NameExpr( decl->location, "receive" ) )
     345                    new SingleInit( decl->location, new NameExpr( decl->location, "__CFA_receive_wrap" ) )
    262346                )
    263347            ));
     
    267351            genericReceive->params.push_back( new ReferenceType( new StructInstType( *actorDecl ) ) );
    268352            genericReceive->params.push_back( new ReferenceType( new StructInstType( *msgDecl ) ) );
     353            genericReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *actorDecl ) ) ) );
     354            genericReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *msgDecl ) ) ) );
    269355            genericReceive->returns.push_back( new EnumInstType( *allocationDecl ) );
    270356
     
    285371            ));
    286372
    287             // Generates: new_req{ &receiver, &msg, fn };
     373            // Generates: new_req{ (actor *)&receiver, (message *)&msg, fn };
    288374            sendBody->push_back( new ExprStmt(
    289375                decl->location,
     
    293379                                        {
    294380                                                new NameExpr( decl->location, "new_req" ),
    295                         new AddressExpr( new NameExpr( decl->location, "receiver" ) ),
    296                         new AddressExpr( new NameExpr( decl->location, "msg" ) ),
     381                        new CastExpr( decl->location, new AddressExpr( new NameExpr( decl->location, "receiver" ) ), new PointerType( new StructInstType( *actorDecl ) ), ExplicitCast ),
     382                        new CastExpr( decl->location, new AddressExpr( new NameExpr( decl->location, "msg" ) ), new PointerType( new StructInstType( *msgDecl ) ), ExplicitCast ),
    297383                        new NameExpr( decl->location, "fn" )
    298384                                        }
     
    321407            FunctionDecl * sendOperatorFunction = new FunctionDecl(
    322408                decl->location,
    323                 "?<<?",
     409                "?|?",
    324410                {},                     // forall
    325411                {
  • src/GenPoly/SpecializeNew.cpp

    r0b0a285 rc84dd61  
    113113        using namespace ResolvExpr;
    114114        ast::OpenVarSet openVars, closedVars;
    115         ast::AssertionSet need, have;
    116         findOpenVars( formalType, openVars, closedVars, need, have, FirstClosed );
    117         findOpenVars( actualType, openVars, closedVars, need, have, FirstOpen );
     115        ast::AssertionSet need, have; // unused
     116        ast::TypeEnvironment env; // unused
     117        // findOpenVars( formalType, openVars, closedVars, need, have, FirstClosed );
     118        findOpenVars( actualType, openVars, closedVars, need, have, env, FirstOpen );
    118119        for ( const ast::OpenVarSet::value_type & openVar : openVars ) {
    119120                const ast::Type * boundType = subs->lookup( openVar.first );
     
    125126                        if ( closedVars.find( *inst ) == closedVars.end() ) {
    126127                                return true;
     128                        }
     129                        else {
     130                                assertf(false, "closed: %s", inst->name.c_str());
    127131                        }
    128132                // Otherwise, the variable is bound to a concrete type.
  • src/Parser/DeclarationNode.cc

    r0b0a285 rc84dd61  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Sat May 16 12:34:05 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Apr 20 11:46:00 2023
    13 // Update Count     : 1393
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jun 17 14:41:48 2023
     13// Update Count     : 1405
    1414//
    1515
     
    459459        std::vector<ast::ptr<ast::Expr>> exprs;
    460460        buildList( expr, exprs );
    461         newnode->attributes.push_back(
    462                 new ast::Attribute( *name, std::move( exprs ) ) );
     461        newnode->attributes.push_back( new ast::Attribute( *name, std::move( exprs ) ) );
    463462        delete name;
    464463        return newnode;
     
    633632                                        dst->basictype = src->basictype;
    634633                                } else if ( src->basictype != DeclarationNode::NoBasicType )
    635                                         SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::basicTypeNames[ src->basictype ] + " in type: " );
     634                                        SemanticError( yylloc, string( "multiple declaration types \"" ) + DeclarationNode::basicTypeNames[ dst->basictype ] +
     635                                                                   "\" and \"" + DeclarationNode::basicTypeNames[ src->basictype ] + "\"." );
    636636
    637637                                if ( dst->complextype == DeclarationNode::NoComplexType ) {
    638638                                        dst->complextype = src->complextype;
    639639                                } else if ( src->complextype != DeclarationNode::NoComplexType )
    640                                         SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::complexTypeNames[ src->complextype ] + " in type: " );
     640                                        SemanticError( yylloc, string( "multiple declaration types \"" ) + DeclarationNode::complexTypeNames[ src->complextype ] +
     641                                                                   "\" and \"" + DeclarationNode::complexTypeNames[ src->complextype ] + "\"." );
    641642
    642643                                if ( dst->signedness == DeclarationNode::NoSignedness ) {
    643644                                        dst->signedness = src->signedness;
    644645                                } else if ( src->signedness != DeclarationNode::NoSignedness )
    645                                         SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::signednessNames[ src->signedness ] + " in type: " );
     646                                        SemanticError( yylloc, string( "conflicting type specifier \"" ) + DeclarationNode::signednessNames[ dst->signedness ] +
     647                                                                   "\" and \"" + DeclarationNode::signednessNames[ src->signedness ] + "\"." );
    646648
    647649                                if ( dst->length == DeclarationNode::NoLength ) {
     
    650652                                        dst->length = DeclarationNode::LongLong;
    651653                                } else if ( src->length != DeclarationNode::NoLength )
    652                                         SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::lengthNames[ src->length ] + " in type: " );
     654                                        SemanticError( yylloc, string( "conflicting type specifier \"" ) + DeclarationNode::lengthNames[ dst->length ] +
     655                                                                   "\" and \"" + DeclarationNode::lengthNames[ src->length ] + "\"." );
    653656                        } // if
    654657                        break;
     
    718721
    719722DeclarationNode * DeclarationNode::addEnumBase( DeclarationNode * o ) {
    720         if ( o && o -> type)  {
     723        if ( o && o->type)  {
    721724                type->base= o->type;
    722         }
     725        } // if
    723726        delete o;
    724727        return this;
     
    10031006}
    10041007
    1005 // If a typedef wraps an anonymous declaration, name the inner declaration
    1006 // so it has a consistent name across translation units.
     1008// If a typedef wraps an anonymous declaration, name the inner declaration so it has a consistent name across
     1009// translation units.
    10071010static void nameTypedefedDecl(
    10081011                DeclarationNode * innerDecl,
     
    10851088}
    10861089
    1087 void buildList( DeclarationNode * firstNode,
    1088                 std::vector<ast::ptr<ast::Decl>> & outputList ) {
     1090void buildList( DeclarationNode * firstNode, std::vector<ast::ptr<ast::Decl>> & outputList ) {
    10891091        SemanticErrorException errors;
    10901092        std::back_insert_iterator<std::vector<ast::ptr<ast::Decl>>> out( outputList );
  • src/Parser/ExpressionNode.cc

    r0b0a285 rc84dd61  
    601601ast::Expr * build_cast( const CodeLocation & location,
    602602                DeclarationNode * decl_node,
    603                 ExpressionNode * expr_node ) {
     603                ExpressionNode * expr_node,
     604                ast::CastExpr::CastKind kind ) {
    604605        ast::Type * targetType = maybeMoveBuildType( decl_node );
    605606        if ( dynamic_cast<ast::VoidType *>( targetType ) ) {
     
    607608                return new ast::CastExpr( location,
    608609                        maybeMoveBuild( expr_node ),
    609                         ast::ExplicitCast );
     610                        ast::ExplicitCast, kind );
    610611        } else {
    611612                return new ast::CastExpr( location,
    612613                        maybeMoveBuild( expr_node ),
    613614                        targetType,
    614                         ast::ExplicitCast );
     615                        ast::ExplicitCast, kind );
    615616        } // if
    616617} // build_cast
  • src/Parser/ExpressionNode.h

    r0b0a285 rc84dd61  
    6969ast::DimensionExpr * build_dimensionref( const CodeLocation &, const std::string * name );
    7070
    71 ast::Expr * build_cast( const CodeLocation &, DeclarationNode * decl_node, ExpressionNode * expr_node );
     71ast::Expr * build_cast( const CodeLocation &, DeclarationNode * decl_node, ExpressionNode * expr_node, ast::CastExpr::CastKind kind = ast::CastExpr::Default );
    7272ast::Expr * build_keyword_cast( const CodeLocation &, ast::AggregateDecl::Aggregate target, ExpressionNode * expr_node );
    7373ast::Expr * build_virtual_cast( const CodeLocation &, DeclarationNode * decl_node, ExpressionNode * expr_node );
  • src/Parser/parser.yy

    r0b0a285 rc84dd61  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jun  7 14:32:28 2023
    13 // Update Count     : 6341
     12// Last Modified On : Sat Jun 17 18:53:24 2023
     13// Update Count     : 6347
    1414//
    1515
     
    931931                { $$ = new ExpressionNode( new ast::VirtualCastExpr( yylloc, maybeMoveBuild( $5 ), maybeMoveBuildType( $3 ) ) ); }
    932932        | '(' RETURN type_no_function ')' cast_expression       // CFA
    933                 { SemanticError( yylloc, "Return cast is currently unimplemented." ); $$ = nullptr; }
     933                { $$ = new ExpressionNode( build_cast( yylloc, $3, $5, ast::CastExpr::Return ) ); }
    934934        | '(' COERCE type_no_function ')' cast_expression       // CFA
    935935                { SemanticError( yylloc, "Coerce cast is currently unimplemented." ); $$ = nullptr; }
     
    10401040                // FIX ME: computes $1 twice
    10411041        | logical_OR_expression '?' /* empty */ ':' conditional_expression // GCC, omitted first operand
    1042                 { $$ = new ExpressionNode( build_cond( yylloc, $1, $1, $4 ) ); }
     1042                { $$ = new ExpressionNode( build_cond( yylloc, $1, $1->clone(), $4 ) ); }
    10431043        ;
    10441044
  • src/ResolvExpr/Candidate.hpp

    r0b0a285 rc84dd61  
    9191
    9292/// Holdover behaviour from old `findMinCost` -- xxx -- can maybe be eliminated?
     93/*
    9394static inline void promoteCvtCost( CandidateList & candidates ) {
    9495        for ( CandidateRef & r : candidates ) {
     
    9697        }
    9798}
     99*/
    98100
    99101void print( std::ostream & os, const Candidate & cand, Indenter indent = {} );
  • src/ResolvExpr/CandidateFinder.cpp

    r0b0a285 rc84dd61  
    3838#include "typeops.h"              // for combos
    3939#include "Unify.h"
     40#include "WidenMode.h"
    4041#include "AST/Expr.hpp"
    4142#include "AST/Node.hpp"
     
    749750                        // attempt to narrow based on expected target type
    750751                        const ast::Type * returnType = funcType->returns.front();
    751                         if ( ! unify(
    752                                 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen )
    753                         ) {
    754                                 // unification failed, do not pursue this candidate
    755                                 return;
     752                        if ( selfFinder.strictMode ) {
     753                                if ( ! unifyExact(
     754                                        returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, noWiden() ) // xxx - is no widening correct?
     755                                ) {
     756                                        // unification failed, do not pursue this candidate
     757                                        return;
     758                                }
     759                        }
     760                        else {
     761                                if ( ! unify(
     762                                        returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen )
     763                                ) {
     764                                        // unification failed, do not pursue this candidate
     765                                        return;
     766                                }
    756767                        }
    757768                }
     
    771782                                for (size_t i=0; i<nParams; ++i) {
    772783                                        auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>();
    773                                         if (!instantiateArgument( location,
     784                                        if ( !instantiateArgument( location,
    774785                                                funcType->params[i], obj->init, args, results, genStart, symtab)) return;
    775786                                }
     
    781792                        // matches
    782793                        // no default args for indirect calls
    783                         if ( ! instantiateArgument( location,
     794                        if ( !instantiateArgument( location,
    784795                                param, nullptr, args, results, genStart, symtab ) ) return;
    785796                }
     
    874885
    875886                if ( auto structInst = aggrExpr->result.as< ast::StructInstType >() ) {
    876                         addAggMembers( structInst, aggrExpr, *cand, Cost::safe, "" );
     887                        addAggMembers( structInst, aggrExpr, *cand, Cost::unsafe, "" );
    877888                } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) {
    878                         addAggMembers( unionInst, aggrExpr, *cand, Cost::safe, "" );
     889                        addAggMembers( unionInst, aggrExpr, *cand, Cost::unsafe, "" );
    879890                }
    880891        }
     
    10071018                                if ( auto pointer = dynamic_cast< const ast::PointerType * >( funcResult ) ) {
    10081019                                        if ( auto function = pointer->base.as< ast::FunctionType >() ) {
     1020                                                // if (!selfFinder.allowVoid && function->returns.empty()) continue;
    10091021                                                CandidateRef newFunc{ new Candidate{ *func } };
    10101022                                                newFunc->expr =
     
    10181030                                        if ( const ast::EqvClass * clz = func->env.lookup( *inst ) ) {
    10191031                                                if ( auto function = clz->bound.as< ast::FunctionType >() ) {
    1020                                                         CandidateRef newFunc{ new Candidate{ *func } };
     1032                                                        CandidateRef newFunc( new Candidate( *func ) );
    10211033                                                        newFunc->expr =
    10221034                                                                referenceToRvalueConversion( newFunc->expr, newFunc->cost );
     
    10601072                if ( found.empty() && ! errors.isEmpty() ) { throw errors; }
    10611073
     1074                // only keep the best matching intrinsic result to match C semantics (no unexpected narrowing/widening)
     1075                // TODO: keep one for each set of argument candidates?
     1076                Cost intrinsicCost = Cost::infinity;
     1077                CandidateList intrinsicResult;
     1078
    10621079                // Compute conversion costs
    10631080                for ( CandidateRef & withFunc : found ) {
     
    10821099                        if ( cvtCost != Cost::infinity ) {
    10831100                                withFunc->cvtCost = cvtCost;
    1084                                 candidates.emplace_back( std::move( withFunc ) );
    1085                         }
    1086                 }
     1101                                withFunc->cost += cvtCost;
     1102                                auto func = withFunc->expr.strict_as<ast::ApplicationExpr>()->func.as<ast::VariableExpr>();
     1103                                if (func && func->var->linkage == ast::Linkage::Intrinsic) {
     1104                                        if (withFunc->cost < intrinsicCost) {
     1105                                                intrinsicResult.clear();
     1106                                                intrinsicCost = withFunc->cost;
     1107                                        }
     1108                                        if (withFunc->cost == intrinsicCost) {
     1109                                                intrinsicResult.emplace_back(std::move(withFunc));
     1110                                        }
     1111                                }
     1112                                else {
     1113                                        candidates.emplace_back( std::move( withFunc ) );
     1114                                }
     1115                        }
     1116                }
     1117                spliceBegin( candidates, intrinsicResult );
    10871118                found = std::move( candidates );
    10881119
    10891120                // use a new list so that candidates are not examined by addAnonConversions twice
    1090                 CandidateList winners = findMinCost( found );
    1091                 promoteCvtCost( winners );
     1121                // CandidateList winners = findMinCost( found );
     1122                // promoteCvtCost( winners );
    10921123
    10931124                // function may return a struct/union value, in which case we need to add candidates
    10941125                // for implicit conversions to each of the anonymous members, which must happen after
    10951126                // `findMinCost`, since anon conversions are never the cheapest
    1096                 for ( const CandidateRef & c : winners ) {
     1127                for ( const CandidateRef & c : found ) {
    10971128                        addAnonConversions( c );
    10981129                }
    1099                 spliceBegin( candidates, winners );
    1100 
    1101                 if ( candidates.empty() && targetType && ! targetType->isVoid() ) {
     1130                // would this be too slow when we don't check cost anymore?
     1131                spliceBegin( candidates, found );
     1132
     1133                if ( candidates.empty() && targetType && ! targetType->isVoid() && !selfFinder.strictMode ) {
    11021134                        // If resolution is unsuccessful with a target type, try again without, since it
    11031135                        // will sometimes succeed when it wouldn't with a target type binding.
     
    11401172
    11411173                CandidateFinder finder( context, tenv, toType );
     1174                if (toType->isVoid()) {
     1175                        finder.allowVoid = true;
     1176                }
     1177                if ( castExpr->kind == ast::CastExpr::Return ) {
     1178                        finder.strictMode = true;
     1179                        finder.find( castExpr->arg, ResolvMode::withAdjustment() );
     1180
     1181                        // return casts are eliminated (merely selecting an overload, no actual operation)
     1182                        candidates = std::move(finder.candidates);
     1183                }
    11421184                finder.find( castExpr->arg, ResolvMode::withAdjustment() );
    11431185
     
    11451187
    11461188                CandidateList matches;
     1189                Cost minExprCost = Cost::infinity;
     1190                Cost minCastCost = Cost::infinity;
    11471191                for ( CandidateRef & cand : finder.candidates ) {
    11481192                        ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have;
     
    11761220                                // count one safe conversion for each value that is thrown away
    11771221                                thisCost.incSafe( discardedValues );
    1178                                 CandidateRef newCand = std::make_shared<Candidate>(
    1179                                         restructureCast( cand->expr, toType, castExpr->isGenerated ),
    1180                                         copy( cand->env ), std::move( open ), std::move( need ), cand->cost,
    1181                                         cand->cost + thisCost );
    1182                                 inferParameters( newCand, matches );
    1183                         }
    1184                 }
    1185 
    1186                 // select first on argument cost, then conversion cost
    1187                 CandidateList minArgCost = findMinCost( matches );
    1188                 promoteCvtCost( minArgCost );
    1189                 candidates = findMinCost( minArgCost );
     1222                                // select first on argument cost, then conversion cost
     1223                                if ( cand->cost < minExprCost || ( cand->cost == minExprCost && thisCost < minCastCost ) ) {
     1224                                        minExprCost = cand->cost;
     1225                                        minCastCost = thisCost;
     1226                                        matches.clear();
     1227
     1228
     1229                                }
     1230                                // ambiguous case, still output candidates to print in error message
     1231                                if ( cand->cost == minExprCost && thisCost == minCastCost ) {
     1232                                        CandidateRef newCand = std::make_shared<Candidate>(
     1233                                                restructureCast( cand->expr, toType, castExpr->isGenerated ),
     1234                                                copy( cand->env ), std::move( open ), std::move( need ), cand->cost + thisCost);
     1235                                        // currently assertions are always resolved immediately so this should have no effect.
     1236                                        // if this somehow changes in the future (e.g. delayed by indeterminate return type)
     1237                                        // we may need to revisit the logic.
     1238                                        inferParameters( newCand, matches );
     1239                                }
     1240                                // else skip, better alternatives found
     1241
     1242                        }
     1243                }
     1244                candidates = std::move(matches);
     1245
     1246                //CandidateList minArgCost = findMinCost( matches );
     1247                //promoteCvtCost( minArgCost );
     1248                //candidates = findMinCost( minArgCost );
    11901249        }
    11911250
     
    14531512                // candidates for true result
    14541513                CandidateFinder finder2( context, tenv );
     1514                finder2.allowVoid = true;
    14551515                finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() );
    14561516                if ( finder2.candidates.empty() ) return;
     
    14581518                // candidates for false result
    14591519                CandidateFinder finder3( context, tenv );
     1520                finder3.allowVoid = true;
    14601521                finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() );
    14611522                if ( finder3.candidates.empty() ) return;
     
    15241585        void Finder::postvisit( const ast::ConstructorExpr * ctorExpr ) {
    15251586                CandidateFinder finder( context, tenv );
     1587                finder.allowVoid = true;
    15261588                finder.find( ctorExpr->callExpr, ResolvMode::withoutPrune() );
    15271589                for ( CandidateRef & r : finder.candidates ) {
     
    16401702                        CandidateFinder finder( context, tenv, toType );
    16411703                        finder.find( initExpr->expr, ResolvMode::withAdjustment() );
     1704
     1705                        Cost minExprCost = Cost::infinity;
     1706                        Cost minCastCost = Cost::infinity;
    16421707                        for ( CandidateRef & cand : finder.candidates ) {
    16431708                                if (reason.code == NotFound) reason.code = NoMatch;
     
    16771742                                        // count one safe conversion for each value that is thrown away
    16781743                                        thisCost.incSafe( discardedValues );
    1679                                         CandidateRef newCand = std::make_shared<Candidate>(
    1680                                                 new ast::InitExpr{
    1681                                                         initExpr->location, restructureCast( cand->expr, toType ),
    1682                                                         initAlt.designation },
    1683                                                 std::move(env), std::move( open ), std::move( need ), cand->cost, thisCost );
    1684                                         inferParameters( newCand, matches );
     1744                                        if ( cand->cost < minExprCost || ( cand->cost == minExprCost && thisCost < minCastCost ) ) {
     1745                                                minExprCost = cand->cost;
     1746                                                minCastCost = thisCost;
     1747                                                matches.clear();
     1748                                        }
     1749                                        // ambiguous case, still output candidates to print in error message
     1750                                        if ( cand->cost == minExprCost && thisCost == minCastCost ) {
     1751                                                CandidateRef newCand = std::make_shared<Candidate>(
     1752                                                        new ast::InitExpr{
     1753                                                                initExpr->location,
     1754                                                                restructureCast( cand->expr, toType ),
     1755                                                                initAlt.designation },
     1756                                                        std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost );
     1757                                                // currently assertions are always resolved immediately so this should have no effect.
     1758                                                // if this somehow changes in the future (e.g. delayed by indeterminate return type)
     1759                                                // we may need to revisit the logic.
     1760                                                inferParameters( newCand, matches );
     1761                                        }
    16851762                                }
    16861763                        }
     
    16881765
    16891766                // select first on argument cost, then conversion cost
    1690                 CandidateList minArgCost = findMinCost( matches );
    1691                 promoteCvtCost( minArgCost );
    1692                 candidates = findMinCost( minArgCost );
     1767                // CandidateList minArgCost = findMinCost( matches );
     1768                // promoteCvtCost( minArgCost );
     1769                // candidates = findMinCost( minArgCost );
     1770                candidates = std::move(matches);
    16931771        }
    16941772
     
    17561834                        auto found = selected.find( mangleName );
    17571835                        if ( found != selected.end() ) {
    1758                                 if ( newCand->cost < found->second.candidate->cost ) {
     1836                                // tiebreaking by picking the lower cost on CURRENT expression
     1837                                // NOTE: this behavior is different from C semantics.
     1838                                // Specific remediations are performed for C operators at postvisit(UntypedExpr).
     1839                                // Further investigations may take place.
     1840                                if ( newCand->cost < found->second.candidate->cost
     1841                                        || (newCand->cost == found->second.candidate->cost && newCand->cvtCost < found->second.candidate->cvtCost) ) {
    17591842                                        PRINT(
    17601843                                                std::cerr << "cost " << newCand->cost << " beats "
     
    17631846
    17641847                                        found->second = PruneStruct{ newCand };
    1765                                 } else if ( newCand->cost == found->second.candidate->cost ) {
     1848                                } else if ( newCand->cost == found->second.candidate->cost && newCand->cvtCost == found->second.candidate->cvtCost ) {
    17661849                                        // if one of the candidates contains a deleted identifier, can pick the other,
    17671850                                        // since deleted expressions should not be ambiguous if there is another option
     
    18541937        */
    18551938
    1856         if ( mode.prune ) {
     1939        // optimization: don't prune for NameExpr since it never has cost
     1940        if ( mode.prune && !dynamic_cast<const ast::NameExpr *>(expr) ) {
    18571941                // trim candidates to single best one
    18581942                PRINT(
  • src/ResolvExpr/CandidateFinder.hpp

    r0b0a285 rc84dd61  
    3333        const ast::TypeEnvironment & env;  ///< Substitutions performed in this resolution
    3434        ast::ptr< ast::Type > targetType;  ///< Target type for resolution
     35        bool strictMode = false;           ///< If set to true, requires targetType to be exact match (inside return cast)
     36        bool allowVoid = false;            ///< If set to true, allow void-returning function calls (only top level, cast to void and first in comma)
    3537        std::set< std::string > otypeKeys;  /// different type may map to same key
    3638
  • src/ResolvExpr/CastCost.cc

    r0b0a285 rc84dd61  
    234234        if ( typesCompatibleIgnoreQualifiers( src, dst, env ) ) {
    235235                PRINT( std::cerr << "compatible!" << std::endl; )
     236                if (dynamic_cast<const ast::ZeroType *>(dst) || dynamic_cast<const ast::OneType *>(dst)) {
     237                        return Cost::spec;
     238                }
    236239                return Cost::zero;
    237240        } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
  • src/ResolvExpr/CommonType.cc

    r0b0a285 rc84dd61  
    697697                        if ( auto basic2 = dynamic_cast< const ast::BasicType * >( type2 ) ) {
    698698                                #warning remove casts when `commonTypes` moved to new AST
     699                               
     700                                /*
    699701                                ast::BasicType::Kind kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)basic2->kind ];
    700702                                if (
     
    706708                                        result = new ast::BasicType{ kind, basic->qualifiers | basic2->qualifiers };
    707709                                }
     710                                */
     711                                ast::BasicType::Kind kind;
     712                                if (basic->kind != basic2->kind && !widen.first && !widen.second) return;
     713                                else if (!widen.first) kind = basic->kind; // widen.second
     714                                else if (!widen.second) kind = basic2->kind;
     715                                else kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)basic2->kind ];
     716                                // xxx - what does qualifiers even do here??
     717                                if ( (basic->qualifiers >= basic2->qualifiers || widen.first)
     718                                        && (basic->qualifiers <= basic2->qualifiers || widen.second) ) {
     719                                        result = new ast::BasicType{ kind, basic->qualifiers | basic2->qualifiers };
     720                                }
     721                               
    708722                        } else if (
    709723                                dynamic_cast< const ast::ZeroType * >( type2 )
     
    712726                                #warning remove casts when `commonTypes` moved to new AST
    713727                                ast::BasicType::Kind kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)ast::BasicType::SignedInt ];
    714                                 if (
    715                                         ( ( kind == basic->kind && basic->qualifiers >= type2->qualifiers )
     728                                /*
     729                                if ( // xxx - what does qualifier even do here??
     730                                        ( ( basic->qualifiers >= type2->qualifiers )
    716731                                                || widen.first )
    717                                         && ( ( kind != basic->kind && basic->qualifiers <= type2->qualifiers )
     732                                         && ( ( /* kind != basic->kind && basic->qualifiers <= type2->qualifiers )
    718733                                                || widen.second )
    719                                 ) {
    720                                         result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers };
     734                                )
     735                                */
     736                                if (widen.second) {
     737                                        result = new ast::BasicType{ basic->kind, basic->qualifiers | type2->qualifiers };
    721738                                }
    722739                        } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) {
     
    746763                                auto entry = open.find( *var );
    747764                                if ( entry != open.end() ) {
     765                                // if (tenv.lookup(*var)) {
    748766                                        ast::AssertionSet need, have;
    749767                                        if ( ! tenv.bindVar(
  • src/ResolvExpr/ConversionCost.cc

    r0b0a285 rc84dd61  
    702702
    703703        cost = costCalc( refType->base, dst, srcIsLvalue, symtab, env );
     704
     705        // xxx - should qualifiers be considered in pass-by-value?
     706        /*
    704707        if ( refType->base->qualifiers == dst->qualifiers ) {
    705708                cost.incReference();
     
    709712                cost.incUnsafe();
    710713        }
     714        */
     715        cost.incReference();
    711716}
    712717
     
    792797                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
    793798                }
     799                // this has the effect of letting any expr such as x+0, x+1 to be typed
     800                // the same as x, instead of at least int. are we willing to sacrifice this little
     801                // bit of coherence with C?
     802                // TODO: currently this does not work when no zero/one overloads exist. Find a fix for it.
     803                // cost = Cost::zero;
    794804        } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
    795805                cost = Cost::zero;
    796806                // +1 for zero_t ->, +1 for disambiguation
    797807                cost.incSafe( maxIntCost + 2 );
     808                // assuming 0p is supposed to be used for pointers?
    798809        }
    799810}
     
    804815                cost = Cost::zero;
    805816        } else if ( const ast::BasicType * dstAsBasic =
    806                         dynamic_cast< const ast::BasicType * >( dst ) ) {
     817                        dynamic_cast< const ast::BasicType * >( dst ) ) {               
    807818                int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ];
    808819                if ( -1 == tableResult ) {
     
    813824                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
    814825                }
     826               
     827                // cost = Cost::zero;
    815828        }
    816829}
  • src/ResolvExpr/FindOpenVars.cc

    r0b0a285 rc84dd61  
    2121#include "AST/Pass.hpp"
    2222#include "AST/Type.hpp"
     23#include "AST/TypeEnvironment.hpp"
    2324#include "Common/PassVisitor.h"
    2425#include "SynTree/Declaration.h"  // for TypeDecl, DeclarationWithType (ptr ...
    2526#include "SynTree/Type.h"         // for Type, Type::ForallList, ArrayType
     27
     28#include <iostream>
    2629
    2730namespace ResolvExpr {
     
    102105                        ast::AssertionSet & need;
    103106                        ast::AssertionSet & have;
     107                        ast::TypeEnvironment & env;
    104108                        bool nextIsOpen;
    105109
    106110                        FindOpenVars_new(
    107111                                ast::OpenVarSet & o, ast::OpenVarSet & c, ast::AssertionSet & n,
    108                                 ast::AssertionSet & h, FirstMode firstIsOpen )
    109                         : open( o ), closed( c ), need( n ), have( h ), nextIsOpen( firstIsOpen ) {}
     112                                ast::AssertionSet & h, ast::TypeEnvironment & env, FirstMode firstIsOpen )
     113                        : open( o ), closed( c ), need( n ), have( h ), env (env), nextIsOpen( firstIsOpen ) {}
    110114
    111115                        void previsit( const ast::FunctionType * type ) {
    112116                                // mark open/closed variables
    113117                                if ( nextIsOpen ) {
     118                                        // trying to remove this from resolver.
     119                                        // occasionally used in other parts so not deleting right now.
     120
     121                                        // insert open variables unbound to environment.
     122                                        env.add(type->forall);
     123
    114124                                        for ( auto & decl : type->forall ) {
    115125                                                open[ *decl ] = ast::TypeData{ decl->base };
     
    137147        void findOpenVars(
    138148                        const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed,
    139                         ast::AssertionSet & need, ast::AssertionSet & have, FirstMode firstIsOpen ) {
    140                 ast::Pass< FindOpenVars_new > finder{ open, closed, need, have, firstIsOpen };
     149                        ast::AssertionSet & need, ast::AssertionSet & have, ast::TypeEnvironment & env, FirstMode firstIsOpen ) {
     150                ast::Pass< FindOpenVars_new > finder{ open, closed, need, have, env, firstIsOpen };
    141151                type->accept( finder );
     152
     153                if (!closed.empty()) {
     154                        std::cerr << "closed: ";
     155                        for (auto& i : closed) {
     156                                std::cerr << i.first.base->location << ":" << i.first.base->name << ' ';
     157                        }
     158                        std::cerr << std::endl;
     159                }
    142160        }
    143161} // namespace ResolvExpr
  • src/ResolvExpr/FindOpenVars.h

    r0b0a285 rc84dd61  
    3333        void findOpenVars(
    3434                const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed,
    35                 ast::AssertionSet & need, ast::AssertionSet & have, FirstMode firstIsOpen );
     35                ast::AssertionSet & need, ast::AssertionSet & have, ast::TypeEnvironment & env, FirstMode firstIsOpen );
    3636} // namespace ResolvExpr
    3737
  • src/ResolvExpr/Resolver.cc

    r0b0a285 rc84dd61  
    10111011                        ast::TypeEnvironment env;
    10121012                        CandidateFinder finder( context, env );
     1013                        finder.allowVoid = true;
    10131014                        finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
    10141015                        --recursion_level;
     
    10541055
    10551056                        // promote candidate.cvtCost to .cost
    1056                         promoteCvtCost( winners );
     1057                        // promoteCvtCost( winners );
    10571058
    10581059                        // produce ambiguous errors, if applicable
  • src/ResolvExpr/SatisfyAssertions.cpp

    r0b0a285 rc84dd61  
    1616#include "SatisfyAssertions.hpp"
    1717
     18#include <iostream>
    1819#include <algorithm>
    1920#include <cassert>
     
    4546#include "SymTab/Mangler.h"
    4647
     48
     49
    4750namespace ResolvExpr {
    4851
     
    6568                        ast::AssertionSet && h, ast::AssertionSet && n, ast::OpenVarSet && o, ast::UniqueId rs )
    6669                : cdata( c ), adjType( at ), env( std::move( e ) ), have( std::move( h ) ),
    67                   need( std::move( n ) ), open( std::move( o ) ), resnSlot( rs ) {}
     70                  need( std::move( n ) ), open( std::move( o ) ), resnSlot( rs ) {
     71                        if (!have.empty()) {
     72                                // std::cerr << c.id->location << ':' << c.id->name << std::endl; // I think this was debugging code so I commented it
     73                        }
     74                  }
    6875        };
    6976
     
    139146        };
    140147
    141         /// Adds a captured assertion to the symbol table
    142         void addToSymbolTable( const ast::AssertionSet & have, ast::SymbolTable & symtab ) {
    143                 for ( auto & i : have ) {
    144                         if ( i.second.isUsed ) { symtab.addId( i.first->var ); }
    145                 }
    146         }
     148        enum AssertionResult {Fail, Skip, Success} ;
    147149
    148150        /// Binds a single assertion, updating satisfaction state
     
    155157                        "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() );
    156158
    157                 ast::Expr * varExpr = match.cdata.combine( cand->expr->location, cand->cvtCost );
     159                ast::Expr * varExpr = match.cdata.combine( cand->expr->location, cand->cost );
    158160                varExpr->result = match.adjType;
    159161                if ( match.resnSlot ) { varExpr->inferred.resnSlots().emplace_back( match.resnSlot ); }
     
    165167
    166168        /// Satisfy a single assertion
    167         bool satisfyAssertion( ast::AssertionList::value_type & assn, SatState & sat, bool allowConversion = false, bool skipUnbound = false) {
     169        AssertionResult satisfyAssertion( ast::AssertionList::value_type & assn, SatState & sat, bool skipUnbound = false) {
    168170                // skip unused assertions
    169                 if ( ! assn.second.isUsed ) return true;
     171                // static unsigned int cnt = 0; // I think this was debugging code so I commented it
     172                if ( ! assn.second.isUsed ) return AssertionResult::Success;
     173
     174                // if (assn.first->var->name[1] == '|') std::cerr << ++cnt << std::endl; // I think this was debugging code so I commented it
    170175
    171176                // find candidates that unify with the desired type
    172                 AssnCandidateList matches;
     177                AssnCandidateList matches, inexactMatches;
    173178
    174179                std::vector<ast::SymbolTable::IdData> candidates;
     
    179184                                .strict_as<ast::FunctionType>()->params[0]
    180185                                .strict_as<ast::ReferenceType>()->base;
    181                         sat.cand->env.apply(thisArgType);
     186                        // sat.cand->env.apply(thisArgType);
     187
     188                        if (auto inst = thisArgType.as<ast::TypeInstType>()) {
     189                                auto cls = sat.cand->env.lookup(*inst);
     190                                if (cls && cls->bound) thisArgType = cls->bound;
     191                        }
    182192
    183193                        std::string otypeKey = "";
    184194                        if (thisArgType.as<ast::PointerType>()) otypeKey = Mangle::Encoding::pointer;
    185195                        else if (!isUnboundType(thisArgType)) otypeKey = Mangle::mangle(thisArgType, Mangle::Type | Mangle::NoGenericParams);
    186                         else if (skipUnbound) return false;
     196                        else if (skipUnbound) return AssertionResult::Skip;
    187197
    188198                        candidates = sat.symtab.specialLookupId(kind, otypeKey);
     
    212222
    213223                        ast::OpenVarSet closed;
    214                         findOpenVars( toType, newOpen, closed, newNeed, have, FirstClosed );
    215                         findOpenVars( adjType, newOpen, closed, newNeed, have, FirstOpen );
    216                         if ( allowConversion ) {
     224                        // findOpenVars( toType, newOpen, closed, newNeed, have, FirstClosed );
     225                        findOpenVars( adjType, newOpen, closed, newNeed, have, newEnv, FirstOpen );
     226                        ast::TypeEnvironment tempNewEnv {newEnv};
     227
     228                        if ( unifyExact( toType, adjType, tempNewEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) {
     229                                // set up binding slot for recursive assertions
     230                                ast::UniqueId crntResnSlot = 0;
     231                                if ( ! newNeed.empty() ) {
     232                                        crntResnSlot = ++globalResnSlot;
     233                                        for ( auto & a : newNeed ) { a.second.resnSlot = crntResnSlot; }
     234                                }
     235
     236                                matches.emplace_back(
     237                                        cdata, adjType, std::move( tempNewEnv ), std::move( have ), std::move( newNeed ),
     238                                        std::move( newOpen ), crntResnSlot );
     239                        }
     240                        else if ( matches.empty() ) {
     241                                // restore invalidated env
     242                                // newEnv = sat.cand->env;
     243                                // newNeed.clear();
    217244                                if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) {
    218245                                        // set up binding slot for recursive assertions
     
    223250                                        }
    224251
    225                                         matches.emplace_back(
     252                                        inexactMatches.emplace_back(
    226253                                                cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),
    227254                                                std::move( newOpen ), crntResnSlot );
    228255                                }
    229256                        }
    230                         else {
    231                                 if ( unifyExact( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) {
    232                                         // set up binding slot for recursive assertions
    233                                         ast::UniqueId crntResnSlot = 0;
    234                                         if ( ! newNeed.empty() ) {
    235                                                 crntResnSlot = ++globalResnSlot;
    236                                                 for ( auto & a : newNeed ) { a.second.resnSlot = crntResnSlot; }
    237                                         }
    238 
    239                                         matches.emplace_back(
    240                                                 cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),
    241                                                 std::move( newOpen ), crntResnSlot );
    242                                 }
    243                         }
    244257                }
    245258
    246259                // break if no satisfying match
    247                 if ( matches.empty() ) return false;
     260                if ( matches.empty() ) matches = std::move(inexactMatches);
     261                if ( matches.empty() ) return AssertionResult::Fail;
    248262
    249263                // defer if too many satisfying matches
    250264                if ( matches.size() > 1 ) {
    251265                        sat.deferred.emplace_back( assn.first, assn.second, std::move( matches ) );
    252                         return true;
     266                        return AssertionResult::Success;
    253267                }
    254268
    255269                // otherwise bind unique match in ongoing scope
    256270                AssnCandidate & match = matches.front();
    257                 addToSymbolTable( match.have, sat.symtab );
     271                // addToSymbolTable( match.have, sat.symtab );
    258272                sat.newNeed.insert( match.need.begin(), match.need.end() );
    259273                sat.cand->env = std::move( match.env );
     
    261275
    262276                bindAssertion( assn.first, assn.second, sat.cand, match, sat.inferred );
    263                 return true;
     277                return AssertionResult::Success;
    264278        }
    265279
     
    438452                // for each current mutually-compatible set of assertions
    439453                for ( SatState & sat : sats ) {
    440                         bool allowConversion = false;
    441454                        // stop this branch if a better option is already found
    442455                        auto it = thresholds.find( pruneKey( *sat.cand ) );
     
    447460                        for (unsigned resetCount = 0; ; ++resetCount) {
    448461                                ast::AssertionList next;
    449                                 resetTyVarRenaming();
    450462                                // make initial pass at matching assertions
    451463                                for ( auto & assn : sat.need ) {
     464                                        resetTyVarRenaming();
    452465                                        // fail early if any assertion is not satisfiable
    453                                         if ( ! satisfyAssertion( assn, sat, allowConversion, !next.empty() ) ) {
    454                                                 next.emplace_back(assn);
    455                                                 // goto nextSat;
    456                                         }
    457                                 }
    458                                 // success
    459                                 if (next.empty()) break;
    460                                 // fail if nothing resolves
    461                                 else if (next.size() == sat.need.size()) {
    462                                         if (allowConversion) {
     466                                        auto result = satisfyAssertion( assn, sat, !next.empty() );
     467                                        if ( result == AssertionResult::Fail ) {
    463468                                                Indenter tabs{ 3 };
    464469                                                std::ostringstream ss;
     
    466471                                                print( ss, *sat.cand, ++tabs );
    467472                                                ss << (tabs-1) << "Could not satisfy assertion:\n";
    468                                                 ast::print( ss, next[0].first, tabs );
     473                                                ast::print( ss, assn.first, tabs );
    469474
    470475                                                errors.emplace_back( ss.str() );
    471476                                                goto nextSat;
    472477                                        }
    473 
    474                                         else {
    475                                                 allowConversion = true;
    476                                                 continue;
    477                                         }
    478                                 }
    479                                 allowConversion = false;
     478                                        else if ( result == AssertionResult::Skip ) {
     479                                                next.emplace_back(assn);
     480                                                // goto nextSat;
     481                                        }
     482                                }
     483                                // success
     484                                if (next.empty()) break;
     485
    480486                                sat.need = std::move(next);
    481487                        }
     
    531537                                                sat.cand->expr, std::move( compat.env ), std::move( compat.open ),
    532538                                                ast::AssertionSet{} /* need moved into satisfaction state */,
    533                                                 sat.cand->cost, sat.cand->cvtCost );
     539                                                sat.cand->cost );
    534540
    535541                                        ast::AssertionSet nextNewNeed{ sat.newNeed };
     
    544550                                        for ( DeferRef r : compat.assns ) {
    545551                                                AssnCandidate match = r.match;
    546                                                 addToSymbolTable( match.have, nextSymtab );
     552                                                // addToSymbolTable( match.have, nextSymtab );
    547553                                                nextNewNeed.insert( match.need.begin(), match.need.end() );
    548554
  • src/ResolvExpr/Unify.cc

    r0b0a285 rc84dd61  
    160160                env.apply( newSecond );
    161161
    162                 findOpenVars( newFirst, open, closed, need, have, FirstClosed );
    163                 findOpenVars( newSecond, open, closed, need, have, FirstOpen );
     162                // findOpenVars( newFirst, open, closed, need, have, FirstClosed );
     163                findOpenVars( newSecond, open, closed, need, have, newEnv, FirstOpen );
    164164
    165165                return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden() );
     
    964964                        // check that the other type is compatible and named the same
    965965                        auto otherInst = dynamic_cast< const XInstType * >( other );
    966                         if (otherInst && inst->name == otherInst->name) this->result = otherInst;
     966                        if (otherInst && inst->name == otherInst->name)
     967                                this->result = otherInst;
    967968                        return otherInst;
    968969                }
     
    10491050
    10501051                void postvisit( const ast::TypeInstType * typeInst ) {
    1051                         assert( open.find( *typeInst ) == open.end() );
    1052                         handleRefType( typeInst, type2 );
     1052                        // assert( open.find( *typeInst ) == open.end() );
     1053                        auto otherInst = dynamic_cast< const ast::TypeInstType * >( type2 );
     1054                        if (otherInst && typeInst->name == otherInst->name)
     1055                                this->result = otherInst;
     1056                        // return otherInst;
    10531057                }
    10541058
     
    11611165        ) {
    11621166                ast::OpenVarSet closed;
    1163                 findOpenVars( type1, open, closed, need, have, FirstClosed );
    1164                 findOpenVars( type2, open, closed, need, have, FirstOpen );
     1167                // findOpenVars( type1, open, closed, need, have, FirstClosed );
     1168                findOpenVars( type2, open, closed, need, have, env, FirstOpen );
    11651169                return unifyInexact(
    11661170                        type1, type2, env, need, have, open, WidenMode{ true, true }, common );
     
    11791183                        entry1 = var1 ? open.find( *var1 ) : open.end(),
    11801184                        entry2 = var2 ? open.find( *var2 ) : open.end();
    1181                 bool isopen1 = entry1 != open.end();
    1182                 bool isopen2 = entry2 != open.end();
    1183 
     1185                // bool isopen1 = entry1 != open.end();
     1186                // bool isopen2 = entry2 != open.end();
     1187                bool isopen1 = var1 && env.lookup(*var1);
     1188                bool isopen2 = var2 && env.lookup(*var2);
     1189
     1190                /*
    11841191                if ( isopen1 && isopen2 ) {
    11851192                        if ( entry1->second.kind != entry2->second.kind ) return false;
     
    11901197                        return env.bindVar( var1, type2, entry1->second, need, have, open, widen );
    11911198                } else if ( isopen2 ) {
    1192                         return env.bindVar( var2, type1, entry2->second, need, have, open, widen );
    1193                 } else {
     1199                        return env.bindVar( var2, type1, entry2->second, need, have, open, widen, symtab );
     1200                } */
     1201                if ( isopen1 && isopen2 ) {
     1202                        if ( var1->base->kind != var2->base->kind ) return false;
     1203                        return env.bindVarToVar(
     1204                                var1, var2, ast::TypeData{ var1->base->kind, var1->base->sized||var2->base->sized }, need, have,
     1205                                open, widen );
     1206                } else if ( isopen1 ) {
     1207                        return env.bindVar( var1, type2, ast::TypeData{var1->base}, need, have, open, widen );
     1208                } else if ( isopen2 ) {
     1209                        return env.bindVar( var2, type1, ast::TypeData{var2->base}, need, have, open, widen );
     1210                }else {
    11941211                        return ast::Pass<Unify_new>::read(
    11951212                                type1, type2, env, need, have, open, widen );
    11961213                }
     1214               
    11971215        }
    11981216
  • src/SynTree/Expression.cc

    r0b0a285 rc84dd61  
    267267}
    268268
    269 CastExpr::CastExpr( Expression * arg, Type * toType, bool isGenerated ) : arg(arg), isGenerated( isGenerated ) {
     269CastExpr::CastExpr( Expression * arg, Type * toType, bool isGenerated, CastKind kind ) : arg(arg), isGenerated( isGenerated ), kind( kind ) {
    270270        set_result(toType);
    271271}
    272272
    273 CastExpr::CastExpr( Expression * arg, bool isGenerated ) : arg(arg), isGenerated( isGenerated ) {
     273CastExpr::CastExpr( Expression * arg, bool isGenerated, CastKind kind ) : arg(arg), isGenerated( isGenerated ), kind( kind ) {
    274274        set_result( new VoidType( Type::Qualifiers() ) );
    275275}
    276276
    277 CastExpr::CastExpr( const CastExpr & other ) : Expression( other ), arg( maybeClone( other.arg ) ), isGenerated( other.isGenerated ) {
     277CastExpr::CastExpr( const CastExpr & other ) : Expression( other ), arg( maybeClone( other.arg ) ), isGenerated( other.isGenerated ), kind( other.kind ) {
    278278}
    279279
  • src/SynTree/Expression.h

    r0b0a285 rc84dd61  
    271271        bool isGenerated = true;
    272272
    273         CastExpr( Expression * arg, bool isGenerated = true );
    274         CastExpr( Expression * arg, Type * toType, bool isGenerated = true );
     273        enum CastKind {
     274                Default, // C
     275                Coerce, // reinterpret cast
     276                Return  // overload selection
     277        };
     278
     279        CastKind kind = Default;
     280
     281        CastExpr( Expression * arg, bool isGenerated = true, CastKind kind = Default );
     282        CastExpr( Expression * arg, Type * toType, bool isGenerated = true, CastKind kind = Default );
    275283        CastExpr( Expression * arg, void * ) = delete; // prevent accidentally passing pointers for isGenerated in the first constructor
    276284        CastExpr( const CastExpr & other );
  • src/Tuples/TupleAssignment.cc

    r0b0a285 rc84dd61  
    679679
    680680                                ResolvExpr::CandidateFinder finder( crntFinder.context, matcher->env );
     681                                finder.allowVoid = true;
    681682
    682683                                try {
  • src/Validate/Autogen.cpp

    r0b0a285 rc84dd61  
    321321void FuncGenerator::produceDecl( const ast::FunctionDecl * decl ) {
    322322        assert( nullptr != decl->stmts );
     323        assert( decl->type_params.size() == getGenericParams( type ).size() );
    323324
    324325        definitions.push_back( decl );
     
    356357                decl->init = nullptr;
    357358                splice( assertions, decl->assertions );
    358                 oldToNew.emplace( std::make_pair( old_param, decl ) );
     359                oldToNew.emplace( old_param, decl );
    359360                type_params.push_back( decl );
    360361        }
     
    522523        InitTweak::InitExpander_new srcParam( src );
    523524        // Assign to destination.
    524         ast::Expr * dstSelect = new ast::MemberExpr(
     525        ast::MemberExpr * dstSelect = new ast::MemberExpr(
    525526                location,
    526527                field,
     
    574575                }
    575576
    576                 ast::Expr * srcSelect = (srcParam) ? new ast::MemberExpr(
     577                ast::MemberExpr * srcSelect = (srcParam) ? new ast::MemberExpr(
    577578                        location, field, new ast::VariableExpr( location, srcParam )
    578579                ) : nullptr;
  • src/Validate/GenericParameter.cpp

    r0b0a285 rc84dd61  
    120120}
    121121
    122 struct ValidateGenericParamsCore : public ast::WithCodeLocation {
     122bool isSizedPolymorphic( const ast::AggregateDecl * decl ) {
     123        for ( const auto & param : decl->params ) {
     124                if ( param->sized ) return true;
     125        }
     126        return false;
     127}
     128
     129struct ValidateGenericParamsCore :
     130                public ast::WithCodeLocation, public ast::WithGuards {
     131        // Generic parameter filling and checks:
    123132        const ast::StructInstType * previsit( const ast::StructInstType * type ) {
    124133                assert( location );
     
    129138                assert( location );
    130139                return validateGeneric( *location, type );
     140        }
     141
     142        // Check parameter and bitfield combinations:
     143        bool insideSized = false;
     144        void previsit( const ast::StructDecl * decl ) {
     145                if ( isSizedPolymorphic( decl ) && !insideSized ) {
     146                        GuardValue( insideSized ) = true;
     147                }
     148        }
     149
     150        void previsit( const ast::UnionDecl * decl ) {
     151                if ( isSizedPolymorphic( decl ) && !insideSized ) {
     152                        GuardValue( insideSized ) = true;
     153                }
     154        }
     155
     156        void previsit( const ast::ObjectDecl * decl ) {
     157                if ( insideSized && decl->bitfieldWidth ) {
     158                        SemanticError( decl->location, decl,
     159                                "Cannot have bitfields inside a sized polymorphic structure." );
     160                }
    131161        }
    132162};
  • src/Validate/LinkReferenceToTypes.cpp

    r0b0a285 rc84dd61  
    8484                // Just linking in the node.
    8585                auto mut = ast::mutate( type );
    86                 mut->base = const_cast<ast::EnumDecl *>( decl );
     86                mut->base = decl;
    8787                type = mut;
    8888        }
     
    101101                // Just linking in the node.
    102102                auto mut = ast::mutate( type );
    103                 mut->base = const_cast<ast::StructDecl *>( decl );
     103                mut->base = decl;
    104104                type = mut;
    105105        }
     
    118118                // Just linking in the node.
    119119                auto mut = ast::mutate( type );
    120                 mut->base = const_cast<ast::UnionDecl *>( decl );
     120                mut->base = decl;
    121121                type = mut;
    122122        }
     
    141141
    142142        // Just linking in the node.
    143         mut->base = const_cast<ast::TraitDecl *>( decl );
     143        mut->base = decl;
    144144
    145145        // Need to carry over the 'sized' status of each decl in the instance.
     
    203203        }
    204204
    205         // The following section
    206 
    207205        ForwardEnumsType::iterator fwds = forwardEnums.find( decl->name );
    208206        if ( fwds != forwardEnums.end() ) {
  • src/Virtual/VirtualDtor.cpp

    r0b0a285 rc84dd61  
    146146
    147147            CompoundStmt * dtorBody = mutate( decl->stmts.get() );
    148             // Adds the following to the end of any actor/message dtor:
     148            // Adds the following to the start of any actor/message dtor:
    149149            //  __CFA_dtor_shutdown( this );
    150             dtorBody->push_front( new ExprStmt(
    151                 decl->location,
    152                                 new UntypedExpr (
    153                     decl->location,
    154                                         new NameExpr( decl->location, "__CFA_dtor_shutdown" ),
    155                                         {
    156                         new NameExpr( decl->location, decl->params.at(0)->name )
    157                                         }
    158                                 )
    159                         ));
     150            dtorBody->push_front(
     151                new IfStmt( decl->location,
     152                    new UntypedExpr (
     153                        decl->location,
     154                        new NameExpr( decl->location, "__CFA_dtor_shutdown" ),
     155                        {
     156                            new NameExpr( decl->location, decl->params.at(0)->name )
     157                        }
     158                    ),
     159                    new ReturnStmt( decl->location, nullptr )
     160                )
     161            );
    160162            return;
    161163        }
  • src/main.cc

    r0b0a285 rc84dd61  
    2828#include <list>                             // for list
    2929#include <string>                           // for char_traits, operator<<
    30 
    31 using namespace std;
    3230
    3331#include "AST/Convert.hpp"
     
    8886#include "Virtual/VirtualDtor.hpp"           // for implementVirtDtors
    8987
     88using namespace std;
     89
    9090static void NewPass( const char * const name ) {
    9191        Stats::Heap::newPass( name );
     
    335335
    336336                PASS( "Fix Qualified Types", Validate::fixQualifiedTypes, transUnit );
     337                PASS( "Eliminate Typedef", Validate::eliminateTypedef, transUnit );
    337338                PASS( "Hoist Struct", Validate::hoistStruct, transUnit );
    338                 PASS( "Eliminate Typedef", Validate::eliminateTypedef, transUnit );
    339339                PASS( "Validate Generic Parameters", Validate::fillGenericParameters, transUnit );
    340340                PASS( "Translate Dimensions", Validate::translateDimensionParameters, transUnit );
Note: See TracChangeset for help on using the changeset viewer.