Commit ec1e3ced authored by Daniel Clifford's avatar Daniel Clifford Committed by Commit Bot

[torque]: Improve error output

In the process, add a utility functions to automate printing out comma-separated
lists. Also make sure that the << operator applies to "const Type&" rather than
"const Type*" for consistency elsewhere and generally just good practice.

Bug: v8:7793
Change-Id: I488e8383c4a9496552e63601738d6bcca0ca6e80
Reviewed-on: https://chromium-review.googlesource.com/1111854
Commit-Queue: Daniel Clifford <danno@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54038}
parent f703078a
......@@ -13,37 +13,57 @@ namespace torque {
std::ostream& operator<<(std::ostream& os, const Callable& m) {
os << "callable " << m.name() << "(" << m.signature().parameter_types
<< "): " << m.signature().return_type;
<< "): " << *m.signature().return_type;
return os;
}
std::ostream& operator<<(std::ostream& os, const Variable& v) {
os << "variable " << v.name() << ": " << v.type();
os << "variable " << v.name() << ": " << *v.type();
return os;
}
std::ostream& operator<<(std::ostream& os, const Builtin& b) {
os << "builtin " << b.signature().return_type << " " << b.name()
os << "builtin " << *b.signature().return_type << " " << b.name()
<< b.signature().parameter_types;
return os;
}
std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b) {
os << "runtime function " << b.signature().return_type << " " << b.name()
os << "runtime function " << *b.signature().return_type << " " << b.name()
<< b.signature().parameter_types;
return os;
}
std::ostream& operator<<(std::ostream& os, const Generic& g) {
os << "generic " << g.name() << "<";
bool first = true;
for (auto t : g.declaration()->generic_parameters) {
if (!first) {
os << ", ";
void PrintLabel(std::ostream& os, const Label& l, bool with_names) {
os << l.name();
if (l.GetParameterCount() != 0) {
os << "(";
if (with_names) {
PrintCommaSeparatedList(os, l.GetParameters(),
[](Variable* v) -> std::string {
std::stringstream stream;
stream << v->name();
stream << ": ";
stream << *(v->type());
return stream.str();
});
} else {
PrintCommaSeparatedList(
os, l.GetParameters(),
[](Variable* v) -> const Type& { return *(v->type()); });
}
first = false;
os << t << ": type";
os << ")";
}
}
std::ostream& operator<<(std::ostream& os, const Label& l) {
PrintLabel(os, l, true);
return os;
}
std::ostream& operator<<(std::ostream& os, const Generic& g) {
os << "generic " << g.name() << "<";
PrintCommaSeparatedList(os, g.declaration()->generic_parameters);
os << ">";
return os;
......
......@@ -337,9 +337,12 @@ class TypeAlias : public Declarable {
const Type* type_;
};
void PrintLabel(std::ostream& os, const Label& l, bool with_names);
std::ostream& operator<<(std::ostream& os, const Callable& m);
std::ostream& operator<<(std::ostream& os, const Variable& v);
std::ostream& operator<<(std::ostream& os, const Builtin& b);
std::ostream& operator<<(std::ostream& os, const Label& l);
std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b);
std::ostream& operator<<(std::ostream& os, const Generic& g);
......
......@@ -90,7 +90,7 @@ Builtin* DeclarationVisitor::BuiltinDeclarationCommon(
declarations()->LookupGlobalType(OBJECT_TYPE_STRING))) {
std::stringstream stream;
stream << "second parameter to javascript builtin " << decl->name
<< " is " << signature.types()[1] << " but should be Object";
<< " is " << *signature.types()[1] << " but should be Object";
ReportError(stream.str());
}
}
......@@ -256,7 +256,7 @@ void DeclarationVisitor::Visit(VarDeclarationStatement* stmt) {
}
declarations()->DeclareVariable(variable_name, type);
if (global_context_.verbose()) {
std::cout << "declared variable " << variable_name << " with type " << type
std::cout << "declared variable " << variable_name << " with type " << *type
<< "\n";
}
if (stmt->initializer) {
......
......@@ -25,102 +25,6 @@ Signature FileVisitor::MakeSignature(const CallableNodeSignature* signature) {
return result;
}
namespace {
void PrintMacroSignatures(std::stringstream& s,
const std::vector<Macro*>& macros) {
for (Macro* m : macros) {
s << "\n " << m->name() << m->signature();
}
}
} // namespace
Callable* FileVisitor::LookupCall(const std::string& name,
const Arguments& arguments) {
Callable* result = nullptr;
TypeVector parameter_types(arguments.parameters.GetTypeVector());
Declarable* declarable = declarations()->Lookup(name);
if (declarable->IsBuiltin()) {
result = Builtin::cast(declarable);
} else if (declarable->IsRuntimeFunction()) {
result = RuntimeFunction::cast(declarable);
} else if (declarable->IsMacroList()) {
std::vector<Macro*> candidates;
std::vector<Macro*> macros_with_same_name;
for (Macro* m : MacroList::cast(declarable)->list()) {
bool try_bool_context =
arguments.labels.size() == 0 &&
m->signature().return_type == TypeOracle::GetNeverType();
Label* true_label = nullptr;
Label* false_label = nullptr;
if (try_bool_context) {
true_label = declarations()->TryLookupLabel(kTrueLabelName);
false_label = declarations()->TryLookupLabel(kFalseLabelName);
}
if (IsCompatibleSignature(m->signature(), parameter_types,
arguments.labels) ||
(true_label && false_label &&
IsCompatibleSignature(m->signature(), parameter_types,
{true_label, false_label}))) {
candidates.push_back(m);
} else {
macros_with_same_name.push_back(m);
}
}
if (candidates.empty() && macros_with_same_name.empty()) {
return nullptr;
} else if (candidates.empty()) {
std::stringstream stream;
stream << "cannot find macro with name \"" << name
<< "\" and parameter type(s) (" << parameter_types
<< "), candidates are:";
PrintMacroSignatures(stream, macros_with_same_name);
ReportError(stream.str());
}
auto is_better_candidate = [&](Macro* a, Macro* b) {
return ParameterDifference(a->signature().parameter_types.types,
parameter_types)
.StrictlyBetterThan(ParameterDifference(
b->signature().parameter_types.types, parameter_types));
};
Macro* best = *std::min_element(candidates.begin(), candidates.end(),
is_better_candidate);
for (Macro* candidate : candidates) {
if (candidate != best && !is_better_candidate(best, candidate)) {
std::stringstream s;
s << "ambiguous macro \"" << name << "\" with types ("
<< parameter_types << "), candidates:";
PrintMacroSignatures(s, candidates);
ReportError(s.str());
}
}
result = best;
} else {
std::stringstream stream;
stream << "can't call " << declarable->type_name() << " " << name
<< " because it's not callable"
<< ": call parameters were (" << parameter_types << ")";
ReportError(stream.str());
}
size_t caller_size = parameter_types.size();
size_t callee_size = result->signature().types().size();
if (caller_size != callee_size &&
!result->signature().parameter_types.var_args) {
std::stringstream stream;
stream << "parameter count mismatch calling " << *result << " - expected "
<< std::to_string(callee_size) << ", found "
<< std::to_string(caller_size);
ReportError(stream.str());
}
return result;
}
void FileVisitor::QueueGenericSpecialization(
const SpecializationKey& key, CallableNode* callable,
const CallableNodeSignature* signature, base::Optional<Statement*> body) {
......
......@@ -67,8 +67,6 @@ class FileVisitor {
return std::string("p_") + name;
}
Callable* LookupCall(const std::string& name, const Arguments& arguments);
Signature MakeSignature(const CallableNodeSignature* signature);
struct PendingSpecialization {
......
This diff is collapsed.
......@@ -173,6 +173,8 @@ class ImplementationVisitor : public FileVisitor {
ImplementationVisitor* visitor_;
};
Callable* LookupCall(const std::string& name, const Arguments& arguments);
void GenerateChangedVarsFromControlSplit(AstNode* node);
const Type* GetCommonType(const Type* left, const Type* right);
......
......@@ -83,15 +83,8 @@ std::string AbstractType::GetGeneratedTNodeTypeName() const {
std::string FunctionPointerType::ToExplicitString() const {
std::stringstream result;
result << "builtin (";
bool first = true;
for (const Type* t : parameter_types_) {
if (!first) {
result << ", ";
first = false;
}
result << t;
}
result << ") => " << return_type_;
PrintCommaSeparatedList(result, parameter_types_);
result << ") => " << *return_type_;
return result.str();
}
......@@ -116,7 +109,7 @@ std::string UnionType::ToExplicitString() const {
result << " | ";
}
first = false;
result << t;
result << *t;
}
result << ")";
return result.str();
......@@ -148,21 +141,23 @@ std::string UnionType::GetGeneratedTNodeTypeName() const {
return parent()->GetGeneratedTNodeTypeName();
}
std::ostream& operator<<(std::ostream& os, const Signature& sig) {
void PrintSignature(std::ostream& os, const Signature& sig, bool with_names) {
os << "(";
for (size_t i = 0; i < sig.parameter_types.types.size(); ++i) {
if (i > 0) os << ", ";
if (!sig.parameter_names.empty()) os << sig.parameter_names[i] << ": ";
os << sig.parameter_types.types[i];
if (with_names && !sig.parameter_names.empty()) {
os << sig.parameter_names[i] << ": ";
}
os << *sig.parameter_types.types[i];
}
if (sig.parameter_types.var_args) {
if (sig.parameter_names.size()) os << ", ";
os << "...";
}
os << ")";
os << ": " << sig.return_type;
os << ": " << *sig.return_type;
if (sig.labels.empty()) return os;
if (sig.labels.empty()) return;
os << " labels ";
for (size_t i = 0; i < sig.labels.size(); ++i) {
......@@ -171,22 +166,20 @@ std::ostream& operator<<(std::ostream& os, const Signature& sig) {
if (sig.labels[i].types.size() > 0) os << "(" << sig.labels[i].types << ")";
}
}
std::ostream& operator<<(std::ostream& os, const Signature& sig) {
PrintSignature(os, sig, true);
return os;
}
std::ostream& operator<<(std::ostream& os, const TypeVector& types) {
for (size_t i = 0; i < types.size(); ++i) {
if (i > 0) os << ", ";
os << types[i];
}
PrintCommaSeparatedList(os, types);
return os;
}
std::ostream& operator<<(std::ostream& os, const ParameterTypes& p) {
for (size_t i = 0; i < p.types.size(); ++i) {
if (i > 0) os << ", ";
os << p.types[i];
}
PrintCommaSeparatedList(os, p.types);
if (p.var_args) {
if (p.types.size() > 0) os << ", ";
os << "...";
......
......@@ -268,8 +268,8 @@ class UnionType final : public Type {
std::set<const Type*, TypeLess> types_;
};
inline std::ostream& operator<<(std::ostream& os, const Type* t) {
os << t->ToString();
inline std::ostream& operator<<(std::ostream& os, const Type& t) {
os << t.ToString();
return os;
}
......@@ -344,6 +344,7 @@ struct Arguments {
std::vector<Label*> labels;
};
void PrintSignature(std::ostream& os, const Signature& sig, bool with_names);
std::ostream& operator<<(std::ostream& os, const Signature& sig);
bool IsAssignableFrom(const Type* to, const Type* from);
......
......@@ -36,6 +36,49 @@ class Deduplicator {
std::unordered_set<T, base::hash<T>> storage_;
};
template <class C, class T>
void PrintCommaSeparatedList(std::ostream& os, const T& list, C transform) {
bool first = true;
for (auto& e : list) {
if (first) {
first = false;
} else {
os << ", ";
}
os << transform(e);
}
}
template <class T,
typename std::enable_if<
std::is_pointer<typename T::value_type>::value, int>::type = 0>
void PrintCommaSeparatedList(std::ostream& os, const T& list) {
bool first = true;
for (auto& e : list) {
if (first) {
first = false;
} else {
os << ", ";
}
os << *e;
}
}
template <class T,
typename std::enable_if<
!std::is_pointer<typename T::value_type>::value, int>::type = 0>
void PrintCommaSeparatedList(std::ostream& os, const T& list) {
bool first = true;
for (auto& e : list) {
if (first) {
first = false;
} else {
os << ", ";
}
os << e;
}
}
} // namespace torque
} // namespace internal
} // namespace v8
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment