mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +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
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "executable_semantics/interpreter/heap.h"
|
||||
|
||||
#include "executable_semantics/common/error.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
|
||||
namespace Carbon {
|
||||
@@ -33,9 +34,9 @@ void Heap::Write(const Address& a, const Value* v, int line_num) {
|
||||
|
||||
void Heap::CheckAlive(const Address& address, int line_num) {
|
||||
if (!alive_[address.index]) {
|
||||
llvm::errs() << line_num << ": undefined behavior: access to dead value "
|
||||
<< *values_[address.index] << "\n";
|
||||
exit(-1);
|
||||
FATAL_RUNTIME_ERROR(line_num)
|
||||
<< ": undefined behavior: access to dead value "
|
||||
<< *values_[address.index];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,8 +45,7 @@ void Heap::Deallocate(const Address& address) {
|
||||
if (alive_[address.index]) {
|
||||
alive_[address.index] = false;
|
||||
} else {
|
||||
llvm::errs() << "runtime error, deallocating an already dead value\n";
|
||||
exit(-1);
|
||||
FATAL_RUNTIME_ERROR_NO_LINE() << "deallocating an already dead value";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -20,18 +20,18 @@ namespace Carbon {
|
||||
void ExpectType(int line_num, const std::string& context, const Value* expected,
|
||||
const Value* actual) {
|
||||
if (!TypeEqual(expected, actual)) {
|
||||
FatalUserError() << line_num << ": type error in " << context << "\n"
|
||||
<< "expected: " << *expected << "\n"
|
||||
<< "actual: " << *actual;
|
||||
FATAL_COMPILATION_ERROR(line_num) << "type error in " << context << "\n"
|
||||
<< "expected: " << *expected << "\n"
|
||||
<< "actual: " << *actual;
|
||||
}
|
||||
}
|
||||
|
||||
void ExpectPointerType(int line_num, const std::string& context,
|
||||
const Value* actual) {
|
||||
if (actual->tag() != ValKind::PointerType) {
|
||||
FatalUserError() << line_num << ": type error in " << context << "\n"
|
||||
<< "expected a pointer type\n"
|
||||
<< "actual: " << *actual;
|
||||
FATAL_COMPILATION_ERROR(line_num) << "type error in " << context << "\n"
|
||||
<< "expected a pointer type\n"
|
||||
<< "actual: " << *actual;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,20 +258,13 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values,
|
||||
switch (e->tag()) {
|
||||
case ExpressionKind::BindingExpression: {
|
||||
if (context != TCContext::PatternContext) {
|
||||
llvm::errs()
|
||||
<< e->line_num
|
||||
<< ": compilation error, pattern variables are only allowed in "
|
||||
"pattern context"
|
||||
<< "\n";
|
||||
exit(-1);
|
||||
FATAL_COMPILATION_ERROR(e->line_num)
|
||||
<< "pattern variables are only allowed in pattern context";
|
||||
}
|
||||
auto t = InterpExp(values, e->GetBindingExpression().type);
|
||||
if (t->tag() == ValKind::AutoType) {
|
||||
if (expected == nullptr) {
|
||||
llvm::errs() << e->line_num
|
||||
<< ": compilation error, auto not allowed here"
|
||||
<< "\n";
|
||||
exit(-1);
|
||||
FATAL_COMPILATION_ERROR(e->line_num) << " auto not allowed here";
|
||||
} else {
|
||||
t = expected;
|
||||
}
|
||||
@@ -297,18 +290,15 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values,
|
||||
std::string f = std::to_string(i);
|
||||
const Value* field_t = t->GetTupleValue().FindField(f);
|
||||
if (field_t == nullptr) {
|
||||
llvm::errs() << e->line_num << ": compilation error, field " << f
|
||||
<< " is not in the tuple " << *t << "\n";
|
||||
exit(-1);
|
||||
FATAL_COMPILATION_ERROR(e->line_num)
|
||||
<< "field " << f << " is not in the tuple " << *t;
|
||||
}
|
||||
auto new_e = Expression::MakeIndexExpression(
|
||||
e->line_num, res.exp, Expression::MakeIntLiteral(e->line_num, i));
|
||||
return TCResult(new_e, field_t, res.types);
|
||||
}
|
||||
default:
|
||||
llvm::errs() << e->line_num
|
||||
<< ": compilation error, expected a tuple\n";
|
||||
exit(-1);
|
||||
FATAL_COMPILATION_ERROR(e->line_num) << "expected a tuple";
|
||||
}
|
||||
}
|
||||
case ExpressionKind::TupleLiteral: {
|
||||
@@ -316,15 +306,11 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values,
|
||||
std::vector<TupleElement> arg_types;
|
||||
auto new_types = types;
|
||||
if (expected && expected->tag() != ValKind::TupleValue) {
|
||||
llvm::errs() << e->line_num
|
||||
<< ": compilation error, didn't expect a tuple\n";
|
||||
exit(-1);
|
||||
FATAL_COMPILATION_ERROR(e->line_num) << "didn't expect a tuple";
|
||||
}
|
||||
if (expected && e->GetTupleLiteral().fields.size() !=
|
||||
expected->GetTupleValue().elements.size()) {
|
||||
llvm::errs() << e->line_num
|
||||
<< ": compilation error, tuples of different length\n";
|
||||
exit(-1);
|
||||
FATAL_COMPILATION_ERROR(e->line_num) << "tuples of different length";
|
||||
}
|
||||
int i = 0;
|
||||
for (auto arg = e->GetTupleLiteral().fields.begin();
|
||||
@@ -332,12 +318,10 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values,
|
||||
const Value* arg_expected = nullptr;
|
||||
if (expected && expected->tag() == ValKind::TupleValue) {
|
||||
if (expected->GetTupleValue().elements[i].name != arg->name) {
|
||||
llvm::errs()
|
||||
<< e->line_num
|
||||
<< ": compilation error, field names do not match, expected "
|
||||
FATAL_COMPILATION_ERROR(e->line_num)
|
||||
<< "field names do not match, expected "
|
||||
<< expected->GetTupleValue().elements[i].name << " but got "
|
||||
<< arg->name << "\n";
|
||||
exit(-1);
|
||||
<< arg->name;
|
||||
}
|
||||
arg_expected = expected->GetTupleValue().elements[i].value;
|
||||
}
|
||||
@@ -373,11 +357,10 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values,
|
||||
return TCResult(new_e, method.second, res.types);
|
||||
}
|
||||
}
|
||||
llvm::errs() << e->line_num << ": compilation error, struct "
|
||||
<< t->GetStructType().name
|
||||
<< " does not have a field named "
|
||||
<< e->GetFieldAccessExpression().field << "\n";
|
||||
exit(-1);
|
||||
FATAL_COMPILATION_ERROR(e->line_num)
|
||||
<< "struct " << t->GetStructType().name
|
||||
<< " does not have a field named "
|
||||
<< e->GetFieldAccessExpression().field;
|
||||
case ValKind::TupleValue:
|
||||
for (const TupleElement& field : t->GetTupleValue().elements) {
|
||||
if (e->GetFieldAccessExpression().field == field.name) {
|
||||
@@ -386,11 +369,10 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values,
|
||||
return TCResult(new_e, field.value, res.types);
|
||||
}
|
||||
}
|
||||
llvm::errs() << e->line_num << ": compilation error, struct "
|
||||
<< t->GetStructType().name
|
||||
<< " does not have a field named "
|
||||
<< e->GetFieldAccessExpression().field << "\n";
|
||||
exit(-1);
|
||||
FATAL_COMPILATION_ERROR(e->line_num)
|
||||
<< "struct " << t->GetStructType().name
|
||||
<< " does not have a field named "
|
||||
<< e->GetFieldAccessExpression().field;
|
||||
case ValKind::ChoiceType:
|
||||
for (auto vt = t->GetChoiceType().alternatives.begin();
|
||||
vt != t->GetChoiceType().alternatives.end(); ++vt) {
|
||||
@@ -401,18 +383,15 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values,
|
||||
return TCResult(new_e, fun_ty, res.types);
|
||||
}
|
||||
}
|
||||
llvm::errs() << e->line_num << ": compilation error, struct "
|
||||
<< t->GetStructType().name
|
||||
<< " does not have a field named "
|
||||
<< e->GetFieldAccessExpression().field << "\n";
|
||||
exit(-1);
|
||||
FATAL_COMPILATION_ERROR(e->line_num)
|
||||
<< "struct " << t->GetStructType().name
|
||||
<< " does not have a field named "
|
||||
<< e->GetFieldAccessExpression().field;
|
||||
|
||||
default:
|
||||
llvm::errs()
|
||||
<< e->line_num
|
||||
<< ": compilation error in field access, expected a struct\n"
|
||||
<< *e << "\n";
|
||||
exit(-1);
|
||||
FATAL_COMPILATION_ERROR(e->line_num)
|
||||
<< "field access, expected a struct\n"
|
||||
<< *e;
|
||||
}
|
||||
}
|
||||
case ExpressionKind::IdentifierExpression: {
|
||||
@@ -421,9 +400,8 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values,
|
||||
if (type) {
|
||||
return TCResult(e, *type, types);
|
||||
} else {
|
||||
llvm::errs() << e->line_num << ": could not find `"
|
||||
<< e->GetIdentifierExpression().name << "`\n";
|
||||
exit(-1);
|
||||
FATAL_COMPILATION_ERROR(e->line_num)
|
||||
<< "could not find `" << e->GetIdentifierExpression().name << "`";
|
||||
}
|
||||
}
|
||||
case ExpressionKind::IntLiteral:
|
||||
@@ -522,10 +500,9 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values,
|
||||
return TCResult(new_e, return_type, arg_res.types);
|
||||
}
|
||||
default: {
|
||||
llvm::errs() << e->line_num
|
||||
<< ": compilation error in call, expected a function\n"
|
||||
<< *e << "\n";
|
||||
exit(-1);
|
||||
FATAL_COMPILATION_ERROR(e->line_num)
|
||||
<< "in call, expected a function\n"
|
||||
<< *e;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -722,9 +699,8 @@ auto CheckOrEnsureReturn(const Statement* stmt, bool void_return, int line_num)
|
||||
return Statement::MakeReturn(line_num,
|
||||
Expression::MakeTupleLiteral(line_num, {}));
|
||||
} else {
|
||||
llvm::errs()
|
||||
<< "control-flow reaches end of non-void function without a return\n";
|
||||
exit(-1);
|
||||
FATAL_COMPILATION_ERROR(line_num)
|
||||
<< "control-flow reaches end of non-void function without a return";
|
||||
}
|
||||
}
|
||||
switch (stmt->tag()) {
|
||||
@@ -778,11 +754,8 @@ auto CheckOrEnsureReturn(const Statement* stmt, bool void_return, int line_num)
|
||||
Statement::MakeReturn(stmt->line_num, Expression::MakeTupleLiteral(
|
||||
stmt->line_num, {})));
|
||||
} else {
|
||||
llvm::errs()
|
||||
<< stmt->line_num
|
||||
<< ": control-flow reaches end of non-void function without a "
|
||||
"return\n";
|
||||
exit(-1);
|
||||
FATAL_COMPILATION_ERROR(stmt->line_num)
|
||||
<< "control-flow reaches end of non-void function without a return";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -972,8 +945,8 @@ auto TopLevel(std::list<Declaration>* fs) -> TypeCheckContext {
|
||||
}
|
||||
|
||||
if (found_main == false) {
|
||||
llvm::errs() << "error, program must contain a function named `main`\n";
|
||||
exit(-1);
|
||||
FATAL_COMPILATION_ERROR_NO_LINE()
|
||||
<< "program must contain a function named `main`";
|
||||
}
|
||||
return tops;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "common/check.h"
|
||||
#include "executable_semantics/common/error.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
|
||||
namespace Carbon {
|
||||
@@ -264,24 +265,21 @@ auto GetMember(const Value* v, const std::string& f, int line_num)
|
||||
const Value* field =
|
||||
v->GetStructValue().inits->GetTupleValue().FindField(f);
|
||||
if (field == nullptr) {
|
||||
llvm::errs() << "runtime error, member " << f << " not in " << *v
|
||||
<< "\n";
|
||||
exit(-1);
|
||||
FATAL_RUNTIME_ERROR(line_num) << "member " << f << " not in " << *v;
|
||||
}
|
||||
return field;
|
||||
}
|
||||
case ValKind::TupleValue: {
|
||||
const Value* field = v->GetTupleValue().FindField(f);
|
||||
if (field == nullptr) {
|
||||
llvm::errs() << "field " << f << " not in " << *v << "\n";
|
||||
exit(-1);
|
||||
FATAL_RUNTIME_ERROR(line_num) << "field " << f << " not in " << *v;
|
||||
}
|
||||
return field;
|
||||
}
|
||||
case ValKind::ChoiceType: {
|
||||
if (FindInVarValues(f, v->GetChoiceType().alternatives) == nullptr) {
|
||||
llvm::errs() << "alternative " << f << " not in " << *v << "\n";
|
||||
exit(-1);
|
||||
FATAL_RUNTIME_ERROR(line_num)
|
||||
<< "alternative " << f << " not in " << *v;
|
||||
}
|
||||
return Value::MakeAlternativeConstructorValue(f, v->GetChoiceType().name);
|
||||
}
|
||||
@@ -323,8 +321,8 @@ auto SetFieldImpl(const Value* value,
|
||||
return element.name == *path_begin;
|
||||
});
|
||||
if (it == elements.end()) {
|
||||
llvm::errs() << "field " << *path_begin << " not in " << *value << "\n";
|
||||
exit(-1);
|
||||
FATAL_RUNTIME_ERROR(line_num)
|
||||
<< "field " << *path_begin << " not in " << *value;
|
||||
}
|
||||
it->value = SetFieldImpl(it->value, path_begin + 1, path_end, field_value,
|
||||
line_num);
|
||||
|
||||
Reference in New Issue
Block a user