mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-30 17:45:01 +01:00
Clarify and simplify handling of lvalues (#956)
- Rename `PointerValue` to `LValue` to reflect how it's actually used. We can introduce a `PointerValue` type when we add support for actual pointer values. - Remove support for pattern assignment. It's unclear if Carbon will support this, and even if we do, it raises questions that should first be addressed in a language proposal, like "is the left-hand side of `(x, y) = (1, 2)` an lvalue, or a pattern, or both, or something else entirely?"
This commit is contained in:
@@ -291,57 +291,6 @@ auto Interpreter::PatternMatch(Nonnull<const Value*> p, Nonnull<const Value*> v,
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::PatternAssignment(Nonnull<const Value*> pat,
|
||||
Nonnull<const Value*> val,
|
||||
SourceLocation source_loc) {
|
||||
switch (pat->kind()) {
|
||||
case Value::Kind::PointerValue:
|
||||
heap_.Write(cast<PointerValue>(*pat).value(), val, source_loc);
|
||||
break;
|
||||
case Value::Kind::TupleValue: {
|
||||
switch (val->kind()) {
|
||||
case Value::Kind::TupleValue: {
|
||||
const auto& pat_tup = cast<TupleValue>(*pat);
|
||||
const auto& val_tup = cast<TupleValue>(*val);
|
||||
if (pat_tup.elements().size() != val_tup.elements().size()) {
|
||||
FATAL_RUNTIME_ERROR(source_loc)
|
||||
<< "arity mismatch in tuple pattern assignment:\n pattern: "
|
||||
<< pat_tup << "\n value: " << val_tup;
|
||||
}
|
||||
for (size_t i = 0; i < pat_tup.elements().size(); ++i) {
|
||||
PatternAssignment(pat_tup.elements()[i], val_tup.elements()[i],
|
||||
source_loc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
FATAL() << "expected a tuple value on right-hand-side, not " << *val;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Value::Kind::AlternativeValue: {
|
||||
switch (val->kind()) {
|
||||
case Value::Kind::AlternativeValue: {
|
||||
const auto& pat_alt = cast<AlternativeValue>(*pat);
|
||||
const auto& val_alt = cast<AlternativeValue>(*val);
|
||||
CHECK(val_alt.choice_name() == pat_alt.choice_name() &&
|
||||
val_alt.alt_name() == pat_alt.alt_name())
|
||||
<< "internal error in pattern assignment";
|
||||
PatternAssignment(&pat_alt.argument(), &val_alt.argument(),
|
||||
source_loc);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
FATAL() << "expected an alternative in left-hand-side, not " << *val;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
CHECK(ValueEqual(pat, val, source_loc))
|
||||
<< "internal error in pattern assignment";
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::StepLvalue() {
|
||||
Action& act = todo_.CurrentAction();
|
||||
const Expression& exp = cast<LValAction>(act).expression();
|
||||
@@ -355,7 +304,7 @@ void Interpreter::StepLvalue() {
|
||||
// -> { {E(x) :: C, E, F} :: S, H}
|
||||
Address pointer =
|
||||
GetFromEnv(exp.source_loc(), cast<IdentifierExpression>(exp).name());
|
||||
Nonnull<const Value*> v = arena_->New<PointerValue>(pointer);
|
||||
Nonnull<const Value*> v = arena_->New<LValue>(pointer);
|
||||
return todo_.FinishAction(v);
|
||||
}
|
||||
case ExpressionKind::FieldAccessExpression: {
|
||||
@@ -367,10 +316,10 @@ void Interpreter::StepLvalue() {
|
||||
} else {
|
||||
// { v :: [].f :: C, E, F} :: S, H}
|
||||
// -> { { &v.f :: C, E, F} :: S, H }
|
||||
Address aggregate = cast<PointerValue>(*act.results()[0]).value();
|
||||
Address aggregate = cast<LValue>(*act.results()[0]).address();
|
||||
Address field = aggregate.SubobjectAddress(
|
||||
cast<FieldAccessExpression>(exp).field());
|
||||
return todo_.FinishAction(arena_->New<PointerValue>(field));
|
||||
return todo_.FinishAction(arena_->New<LValue>(field));
|
||||
}
|
||||
}
|
||||
case ExpressionKind::IndexExpression: {
|
||||
@@ -386,26 +335,14 @@ void Interpreter::StepLvalue() {
|
||||
} else {
|
||||
// { v :: [][i] :: C, E, F} :: S, H}
|
||||
// -> { { &v[i] :: C, E, F} :: S, H }
|
||||
Address aggregate = cast<PointerValue>(*act.results()[0]).value();
|
||||
Address aggregate = cast<LValue>(*act.results()[0]).address();
|
||||
std::string f =
|
||||
std::to_string(cast<IntValue>(*act.results()[1]).value());
|
||||
Address field = aggregate.SubobjectAddress(f);
|
||||
return todo_.FinishAction(arena_->New<PointerValue>(field));
|
||||
}
|
||||
}
|
||||
case ExpressionKind::TupleLiteral: {
|
||||
if (act.pos() <
|
||||
static_cast<int>(cast<TupleLiteral>(exp).fields().size())) {
|
||||
// { { vk :: (f1=v1,..., fk=[],fk+1=ek+1,...) :: C, E, F} :: S,
|
||||
// H}
|
||||
// -> { { ek+1 :: (f1=v1,..., fk=vk, fk+1=[],...) :: C, E, F} :: S,
|
||||
// H}
|
||||
return todo_.Spawn(std::make_unique<LValAction>(
|
||||
cast<TupleLiteral>(exp).fields()[act.pos()]));
|
||||
} else {
|
||||
return todo_.FinishAction(arena_->New<TupleValue>(act.results()));
|
||||
return todo_.FinishAction(arena_->New<LValue>(field));
|
||||
}
|
||||
}
|
||||
case ExpressionKind::TupleLiteral:
|
||||
case ExpressionKind::StructLiteral:
|
||||
case ExpressionKind::StructTypeLiteral:
|
||||
case ExpressionKind::IntLiteral:
|
||||
@@ -431,7 +368,7 @@ auto Interpreter::Convert(Nonnull<const Value*> value,
|
||||
switch (value->kind()) {
|
||||
case Value::Kind::IntValue:
|
||||
case Value::Kind::FunctionValue:
|
||||
case Value::Kind::PointerValue:
|
||||
case Value::Kind::LValue:
|
||||
case Value::Kind::BoolValue:
|
||||
case Value::Kind::NominalClassValue:
|
||||
case Value::Kind::AlternativeValue:
|
||||
@@ -912,9 +849,10 @@ void Interpreter::StepStmt() {
|
||||
} else {
|
||||
// { { v :: (a = []) :: C, E, F} :: S, H}
|
||||
// -> { { C, E, F} :: S, H(a := v)}
|
||||
auto pat = act.results()[0];
|
||||
auto val = Convert(act.results()[1], &assign.lhs().static_type());
|
||||
PatternAssignment(pat, val, stmt.source_loc());
|
||||
const auto& lval = cast<LValue>(*act.results()[0]);
|
||||
Nonnull<const Value*> rval =
|
||||
Convert(act.results()[1], &assign.lhs().static_type());
|
||||
heap_.Write(lval.address(), rval, stmt.source_loc());
|
||||
return todo_.FinishAction();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user