static void typeCall(Output& output, Ast::Call* n, TypeConstraints* constraints) { type(output, n->expr, constraints); for (auto& a: n->args) type(output, a, constraints); if (UNION_CASE(Ident, ne, n->expr)) { if (constraints && ne->targets.size > 1) { vector<Ty*> args; for (auto& a: n->args) args.push_back(astType(a)); constraints->rewrites += reduceCandidates(ne->targets, args); } } // This is important for vararg functions and generates nicer errors for argument count/type mismatch if (UNION_CASE(Function, fnty, astType(n->expr))) { if (isArgumentCountValid(fnty, n->args.size)) { for (size_t i = 0; i < fnty->args.size; ++i) typeMustEqual(n->args[i], fnty->args[i], constraints, output); } else if (!constraints) output.error(n->location, "Expected %d arguments but given %d", int(fnty->args.size), int(n->args.size)); n->type = fnty->ret; } else { Arr<Ty*> args; for (auto& a: n->args) args.push(astType(a)); Ty* ret = UNION_NEW(Ty, Unknown, {}); typeMustEqual(n->expr, UNION_NEW(Ty, Function, { args, ret }), constraints, output); n->type = ret; } }
void QueryInterface::iterativeCoherenceTesting() { solver.unrollToZero(); assert( solver.getCurrentDecisionLevel() == 0 ); assert( !solver.conflictDetected() ); vector< Literal > assumptions; while( !candidates.empty() ) { Var v = candidates.back(); if( !solver.isUndefined( v ) ) { assert( solver.getDecisionLevel( v ) == 0 ); if( solver.isTrue( v ) ) addAnswer( v ); candidates.pop_back(); continue; } assert( solver.isUndefined( v ) ); assumptions.push_back( Literal( v, NEGATIVE ) ); unsigned int result = solver.solve( assumptions ); if( result == COHERENT ) reduceCandidates(); else { assert( result == INCOHERENT ); addAnswer( v ); candidates.pop_back(); } solver.unrollToZero(); assert( solver.getCurrentDecisionLevel() == 0 ); assert( !solver.conflictDetected() ); assumptions.clear(); } }