mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-30 22:02:41 +01:00
Switch from llvm::errs()+exit() to FATAL_USER_ERROR() stream-based handling. (#670)
This is intended to: - Standardize use of line_num (and highlight where no line_num is available). - Standardize indications of runtime/compilation errors. - Make it incrementally easier to write new errors. Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
This commit is contained in:
committed by
GitHub
co-authored by
Chandler Carruth
parent
dcc694c2e0
commit
f0af3cb795
@@ -14,6 +14,7 @@
|
||||
#include "common/check.h"
|
||||
#include "executable_semantics/ast/expression.h"
|
||||
#include "executable_semantics/ast/function_definition.h"
|
||||
#include "executable_semantics/common/error.h"
|
||||
#include "executable_semantics/common/tracing_flag.h"
|
||||
#include "executable_semantics/interpreter/action.h"
|
||||
#include "executable_semantics/interpreter/frame.h"
|
||||
@@ -185,11 +186,7 @@ void CallFunction(int line_num, std::vector<const Value*> operas,
|
||||
std::optional<Env> matches =
|
||||
PatternMatch(operas[0]->GetFunctionValue().param, operas[1], globals,
|
||||
¶ms, line_num);
|
||||
if (!matches) {
|
||||
llvm::errs()
|
||||
<< "internal error in call_function, pattern match failed\n";
|
||||
exit(-1);
|
||||
}
|
||||
CHECK(matches) << "internal error in call_function, pattern match failed";
|
||||
// Create the new frame and push it on the stack
|
||||
auto* scope = new Scope(*matches, params);
|
||||
auto* frame = new Frame(operas[0]->GetFunctionValue().name, Stack(scope),
|
||||
@@ -215,19 +212,15 @@ void CallFunction(int line_num, std::vector<const Value*> operas,
|
||||
break;
|
||||
}
|
||||
default:
|
||||
llvm::errs() << line_num << ": in call, expected a function, not "
|
||||
<< *operas[0] << "\n";
|
||||
exit(-1);
|
||||
FATAL_RUNTIME_ERROR(line_num)
|
||||
<< "in call, expected a function, not " << *operas[0];
|
||||
}
|
||||
}
|
||||
|
||||
void DeallocateScope(int line_num, Scope* scope) {
|
||||
for (const auto& l : scope->locals) {
|
||||
std::optional<Address> a = scope->values.Get(l);
|
||||
if (!a) {
|
||||
llvm::errs() << "internal error in DeallocateScope\n";
|
||||
exit(-1);
|
||||
}
|
||||
CHECK(a);
|
||||
state->heap.Deallocate(*a);
|
||||
}
|
||||
}
|
||||
@@ -277,18 +270,16 @@ auto PatternMatch(const Value* p, const Value* v, Env values,
|
||||
case ValKind::TupleValue: {
|
||||
if (p->GetTupleValue().elements.size() !=
|
||||
v->GetTupleValue().elements.size()) {
|
||||
llvm::errs()
|
||||
<< "runtime error: arity mismatch in tuple pattern match\n";
|
||||
exit(-1);
|
||||
FATAL_RUNTIME_ERROR(line_num)
|
||||
<< "arity mismatch in tuple pattern match";
|
||||
}
|
||||
for (const TupleElement& pattern_element :
|
||||
p->GetTupleValue().elements) {
|
||||
const Value* value_field =
|
||||
v->GetTupleValue().FindField(pattern_element.name);
|
||||
if (value_field == nullptr) {
|
||||
llvm::errs() << "runtime error: field " << pattern_element.name
|
||||
<< "not in " << *v << "\n";
|
||||
exit(-1);
|
||||
FATAL_RUNTIME_ERROR(line_num)
|
||||
<< "field " << pattern_element.name << "not in " << *v;
|
||||
}
|
||||
std::optional<Env> matches = PatternMatch(
|
||||
pattern_element.value, value_field, values, vars, line_num);
|
||||
@@ -365,18 +356,16 @@ void PatternAssignment(const Value* pat, const Value* val, int line_num) {
|
||||
case ValKind::TupleValue: {
|
||||
if (pat->GetTupleValue().elements.size() !=
|
||||
val->GetTupleValue().elements.size()) {
|
||||
llvm::errs()
|
||||
<< "runtime error: arity mismatch in tuple pattern match\n";
|
||||
exit(-1);
|
||||
FATAL_RUNTIME_ERROR(line_num)
|
||||
<< "arity mismatch in tuple pattern match";
|
||||
}
|
||||
for (const TupleElement& pattern_element :
|
||||
pat->GetTupleValue().elements) {
|
||||
const Value* value_field =
|
||||
val->GetTupleValue().FindField(pattern_element.name);
|
||||
if (value_field == nullptr) {
|
||||
llvm::errs() << "runtime error: field " << pattern_element.name
|
||||
<< "not in " << *val << "\n";
|
||||
exit(-1);
|
||||
FATAL_RUNTIME_ERROR(line_num)
|
||||
<< "field " << pattern_element.name << "not in " << *val;
|
||||
}
|
||||
PatternAssignment(pattern_element.value, value_field, line_num);
|
||||
}
|
||||
@@ -394,13 +383,11 @@ void PatternAssignment(const Value* pat, const Value* val, int line_num) {
|
||||
case ValKind::AlternativeValue: {
|
||||
switch (val->tag()) {
|
||||
case ValKind::AlternativeValue: {
|
||||
if (pat->GetAlternativeValue().choice_name !=
|
||||
val->GetAlternativeValue().choice_name ||
|
||||
pat->GetAlternativeValue().alt_name !=
|
||||
val->GetAlternativeValue().alt_name) {
|
||||
llvm::errs() << "internal error in pattern assignment\n";
|
||||
exit(-1);
|
||||
}
|
||||
CHECK(pat->GetAlternativeValue().choice_name ==
|
||||
val->GetAlternativeValue().choice_name &&
|
||||
pat->GetAlternativeValue().alt_name ==
|
||||
val->GetAlternativeValue().alt_name)
|
||||
<< "internal error in pattern assignment";
|
||||
PatternAssignment(pat->GetAlternativeValue().argument,
|
||||
val->GetAlternativeValue().argument, line_num);
|
||||
break;
|
||||
@@ -415,10 +402,8 @@ void PatternAssignment(const Value* pat, const Value* val, int line_num) {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (!ValueEqual(pat, val, line_num)) {
|
||||
llvm::errs() << "internal error in pattern assignment\n";
|
||||
exit(-1);
|
||||
}
|
||||
CHECK(ValueEqual(pat, val, line_num))
|
||||
<< "internal error in pattern assignment";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,9 +423,9 @@ void StepLvalue() {
|
||||
std::optional<Address> pointer =
|
||||
CurrentEnv(state).Get(exp->GetIdentifierExpression().name);
|
||||
if (!pointer) {
|
||||
llvm::errs() << exp->line_num << ": could not find `"
|
||||
<< exp->GetIdentifierExpression().name << "`\n";
|
||||
exit(-1);
|
||||
FATAL_RUNTIME_ERROR(exp->line_num)
|
||||
<< ": could not find `" << exp->GetIdentifierExpression().name
|
||||
<< "`";
|
||||
}
|
||||
const Value* v = Value::MakePointerValue(*pointer);
|
||||
frame->todo.Pop();
|
||||
@@ -520,8 +505,8 @@ void StepLvalue() {
|
||||
case ExpressionKind::AutoTypeLiteral:
|
||||
case ExpressionKind::ContinuationTypeLiteral:
|
||||
case ExpressionKind::BindingExpression: {
|
||||
llvm::errs() << "Can't treat expression as lvalue: " << *exp << "\n";
|
||||
exit(-1);
|
||||
FATAL_RUNTIME_ERROR_NO_LINE()
|
||||
<< "Can't treat expression as lvalue: " << *exp;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -569,20 +554,16 @@ void StepExp() {
|
||||
std::string f = std::to_string(act->results[1]->GetIntValue());
|
||||
const Value* field = tuple->GetTupleValue().FindField(f);
|
||||
if (field == nullptr) {
|
||||
llvm::errs() << "runtime error, field " << f << " not in "
|
||||
<< *tuple << "\n";
|
||||
exit(-1);
|
||||
FATAL_RUNTIME_ERROR_NO_LINE()
|
||||
<< "field " << f << " not in " << *tuple;
|
||||
}
|
||||
frame->todo.Pop(1);
|
||||
frame->todo.Push(Action::MakeValAction(field));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
llvm::errs()
|
||||
<< "runtime type error, expected a tuple in field access, "
|
||||
"not "
|
||||
<< *tuple << "\n";
|
||||
exit(-1);
|
||||
FATAL_RUNTIME_ERROR_NO_LINE()
|
||||
<< "expected a tuple in field access, not " << *tuple;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -636,9 +617,9 @@ void StepExp() {
|
||||
std::optional<Address> pointer =
|
||||
CurrentEnv(state).Get(exp->GetIdentifierExpression().name);
|
||||
if (!pointer) {
|
||||
llvm::errs() << exp->line_num << ": could not find `"
|
||||
<< exp->GetIdentifierExpression().name << "`\n";
|
||||
exit(-1);
|
||||
FATAL_RUNTIME_ERROR(exp->line_num)
|
||||
<< ": could not find `" << exp->GetIdentifierExpression().name
|
||||
<< "`";
|
||||
}
|
||||
const Value* pointee = state->heap.Read(*pointer, exp->line_num);
|
||||
frame->todo.Pop(1);
|
||||
@@ -946,12 +927,9 @@ void StepStmt() {
|
||||
std::optional<Env> matches =
|
||||
PatternMatch(p, v, frame->scopes.Top()->values,
|
||||
&frame->scopes.Top()->locals, stmt->line_num);
|
||||
if (!matches) {
|
||||
llvm::errs()
|
||||
<< stmt->line_num
|
||||
<< ": internal error in variable definition, match failed\n";
|
||||
exit(-1);
|
||||
}
|
||||
CHECK(matches)
|
||||
<< stmt->line_num
|
||||
<< ": internal error in variable definition, match failed";
|
||||
frame->scopes.Top()->values = *matches;
|
||||
frame->todo.Pop(1);
|
||||
}
|
||||
@@ -1101,9 +1079,8 @@ void StepStmt() {
|
||||
void Step() {
|
||||
Frame* frame = state->stack.Top();
|
||||
if (frame->todo.IsEmpty()) {
|
||||
llvm::errs() << "runtime error: fell off end of function " << frame->name
|
||||
<< " without `return`\n";
|
||||
exit(-1);
|
||||
FATAL_RUNTIME_ERROR_NO_LINE()
|
||||
<< "fell off end of function " << frame->name << " without `return`";
|
||||
}
|
||||
|
||||
Action* act = frame->todo.Top();
|
||||
|
||||
Reference in New Issue
Block a user