Refactor Pattern and Member accessors. (#889)

This commit is contained in:
Jon Meow
2021-10-18 10:25:52 -07:00
committed by GitHub
parent b278e4edcf
commit 8bda2ca432
7 changed files with 94 additions and 96 deletions
@@ -131,12 +131,11 @@ void Interpreter::InitEnv(const Declaration& d, Env* env) {
for (Nonnull<const Member*> m : class_def.members()) {
switch (m->kind()) {
case Member::Kind::FieldMember: {
Nonnull<const BindingPattern*> binding =
cast<FieldMember>(*m).Binding();
Nonnull<const Expression*> type_expression =
cast<ExpressionPattern>(*binding->Type()).Expression();
auto type = InterpExp(Env(arena), type_expression);
fields.push_back(make_pair(*binding->Name(), type));
const BindingPattern& binding = cast<FieldMember>(*m).binding();
const Expression& type_expression =
cast<ExpressionPattern>(binding.type()).expression();
auto type = InterpExp(Env(arena), &type_expression);
fields.push_back(make_pair(*binding.name(), type));
break;
}
}
@@ -167,7 +166,7 @@ void Interpreter::InitEnv(const Declaration& d, Env* env) {
// result of evaluating the initializer.
auto v = InterpExp(*env, &var.initializer());
Address a = heap.AllocateValue(v);
env->Set(*var.binding().Name(), a);
env->Set(*var.binding().name(), a);
break;
}
}
@@ -674,20 +673,20 @@ auto Interpreter::StepPattern() -> Transition {
case Pattern::Kind::BindingPattern: {
const auto& binding = cast<BindingPattern>(*pattern);
if (act->pos() == 0) {
return Spawn{arena->New<PatternAction>(binding.Type())};
return Spawn{arena->New<PatternAction>(&binding.type())};
} else {
return Done{arena->New<BindingPlaceholderValue>(binding.Name(),
return Done{arena->New<BindingPlaceholderValue>(binding.name(),
act->results()[0])};
}
}
case Pattern::Kind::TuplePattern: {
const auto& tuple = cast<TuplePattern>(*pattern);
if (act->pos() < static_cast<int>(tuple.Fields().size())) {
if (act->pos() < static_cast<int>(tuple.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 Spawn{arena->New<PatternAction>(tuple.Fields()[act->pos()])};
return Spawn{arena->New<PatternAction>(tuple.fields()[act->pos()])};
} else {
return Done{arena->New<TupleValue>(act->results())};
}
@@ -695,20 +694,20 @@ auto Interpreter::StepPattern() -> Transition {
case Pattern::Kind::AlternativePattern: {
const auto& alternative = cast<AlternativePattern>(*pattern);
if (act->pos() == 0) {
return Spawn{arena->New<ExpressionAction>(alternative.ChoiceType())};
return Spawn{arena->New<ExpressionAction>(&alternative.choice_type())};
} else if (act->pos() == 1) {
return Spawn{arena->New<PatternAction>(alternative.Arguments())};
return Spawn{arena->New<PatternAction>(&alternative.arguments())};
} else {
CHECK(act->pos() == 2);
const auto& choice_type = cast<ChoiceType>(*act->results()[0]);
return Done{arena->New<AlternativeValue>(alternative.AlternativeName(),
return Done{arena->New<AlternativeValue>(alternative.alternative_name(),
choice_type.Name(),
act->results()[1])};
}
}
case Pattern::Kind::ExpressionPattern:
return Delegate{arena->New<ExpressionAction>(
cast<ExpressionPattern>(*pattern).Expression())};
&cast<ExpressionPattern>(*pattern).expression())};
}
}
@@ -726,17 +726,17 @@ auto TypeChecker::TypeCheckPattern(
}
case Pattern::Kind::BindingPattern: {
auto& binding = cast<BindingPattern>(*p);
TypeCheckPattern(binding.Type(), types, values, std::nullopt);
TypeCheckPattern(&binding.type(), types, values, std::nullopt);
Nonnull<const Value*> type =
interpreter.InterpPattern(values, binding.Type());
interpreter.InterpPattern(values, &binding.type());
if (expected) {
if (IsConcreteType(type)) {
ExpectType(p->source_loc(), "name binding", type, *expected);
} else {
std::optional<Env> values = interpreter.PatternMatch(
type, *expected, binding.Type()->source_loc());
type, *expected, binding.type().source_loc());
if (values == std::nullopt) {
FATAL_COMPILATION_ERROR(binding.Type()->source_loc())
FATAL_COMPILATION_ERROR(binding.type().source_loc())
<< "Type pattern '" << *type << "' does not match actual type '"
<< **expected << "'";
}
@@ -746,8 +746,8 @@ auto TypeChecker::TypeCheckPattern(
}
}
ExpectIsConcreteType(binding.source_loc(), type);
if (binding.Name().has_value()) {
types.Set(*binding.Name(), type);
if (binding.name().has_value()) {
types.Set(*binding.name(), type);
}
SetStaticType(&binding, type);
return TCResult(types);
@@ -759,13 +759,13 @@ auto TypeChecker::TypeCheckPattern(
if (expected && (*expected)->kind() != Value::Kind::TupleValue) {
FATAL_COMPILATION_ERROR(p->source_loc()) << "didn't expect a tuple";
}
if (expected && tuple.Fields().size() !=
if (expected && tuple.fields().size() !=
cast<TupleValue>(**expected).Elements().size()) {
FATAL_COMPILATION_ERROR(tuple.source_loc())
<< "tuples of different length";
}
for (size_t i = 0; i < tuple.Fields().size(); ++i) {
Nonnull<Pattern*> field = tuple.Fields()[i];
for (size_t i = 0; i < tuple.fields().size(); ++i) {
Nonnull<Pattern*> field = tuple.fields()[i];
std::optional<Nonnull<const Value*>> expected_field_type;
if (expected) {
expected_field_type = cast<TupleValue>(**expected).Elements()[i];
@@ -781,7 +781,7 @@ auto TypeChecker::TypeCheckPattern(
case Pattern::Kind::AlternativePattern: {
auto& alternative = cast<AlternativePattern>(*p);
Nonnull<const Value*> choice_type =
interpreter.InterpExp(values, alternative.ChoiceType());
interpreter.InterpExp(values, &alternative.choice_type());
if (choice_type->kind() != Value::Kind::ChoiceType) {
FATAL_COMPILATION_ERROR(alternative.source_loc())
<< "alternative pattern does not name a choice type.";
@@ -791,22 +791,22 @@ auto TypeChecker::TypeCheckPattern(
*expected, choice_type);
}
std::optional<Nonnull<const Value*>> parameter_types =
FindInVarValues(alternative.AlternativeName(),
FindInVarValues(alternative.alternative_name(),
cast<ChoiceType>(*choice_type).Alternatives());
if (parameter_types == std::nullopt) {
FATAL_COMPILATION_ERROR(alternative.source_loc())
<< "'" << alternative.AlternativeName()
<< "'" << alternative.alternative_name()
<< "' is not an alternative of " << *choice_type;
}
TCResult arg_results = TypeCheckPattern(alternative.Arguments(), types,
TCResult arg_results = TypeCheckPattern(&alternative.arguments(), types,
values, *parameter_types);
SetStaticType(&alternative, choice_type);
return TCResult(arg_results.types);
}
case Pattern::Kind::ExpressionPattern: {
const auto& expression = cast<ExpressionPattern>(*p).Expression();
TCResult result = TypeCheckExp(expression, types, values);
SetStaticType(p, &expression->static_type());
auto& expression = cast<ExpressionPattern>(*p).expression();
TCResult result = TypeCheckExp(&expression, types, values);
SetStaticType(p, &expression.static_type());
return TCResult(result.types);
}
}
@@ -1097,19 +1097,18 @@ auto TypeChecker::TypeOfClassDef(const ClassDefinition* sd, TypeEnv /*types*/,
for (Nonnull<const Member*> m : sd->members()) {
switch (m->kind()) {
case Member::Kind::FieldMember: {
Nonnull<const BindingPattern*> binding =
cast<FieldMember>(*m).Binding();
if (!binding->Name().has_value()) {
FATAL_COMPILATION_ERROR(binding->source_loc())
const BindingPattern& binding = cast<FieldMember>(*m).binding();
if (!binding.name().has_value()) {
FATAL_COMPILATION_ERROR(binding.source_loc())
<< "Struct members must have names";
}
const auto* binding_type = dyn_cast<ExpressionPattern>(binding->Type());
const auto* binding_type = dyn_cast<ExpressionPattern>(&binding.type());
if (binding_type == nullptr) {
FATAL_COMPILATION_ERROR(binding->source_loc())
FATAL_COMPILATION_ERROR(binding.source_loc())
<< "Struct members must have explicit types";
}
auto type = interpreter.InterpExp(ct_top, binding_type->Expression());
fields.push_back(std::make_pair(*binding->Name(), type));
auto type = interpreter.InterpExp(ct_top, &binding_type->expression());
fields.push_back(std::make_pair(*binding.name(), type));
break;
}
}
@@ -1128,11 +1127,11 @@ static auto GetName(const Declaration& d) -> const std::string& {
return cast<ChoiceDeclaration>(d).name();
case Declaration::Kind::VariableDeclaration: {
const BindingPattern& binding = cast<VariableDeclaration>(d).binding();
if (!binding.Name().has_value()) {
if (!binding.name().has_value()) {
FATAL_COMPILATION_ERROR(binding.source_loc())
<< "Top-level variable declarations must have names";
}
return *binding.Name();
return *binding.name();
}
}
}
@@ -1159,14 +1158,14 @@ void TypeChecker::TypeCheck(Nonnull<Declaration*> d, const TypeEnv& types,
// declaration with annotated types.
TypeCheckExp(&var.initializer(), types, values);
const auto* binding_type =
dyn_cast<ExpressionPattern>(var.binding().Type());
dyn_cast<ExpressionPattern>(&var.binding().type());
if (binding_type == nullptr) {
// TODO: consider adding support for `auto`
FATAL_COMPILATION_ERROR(var.source_loc())
<< "Type of a top-level variable must be an expression.";
}
Nonnull<const Value*> declared_type =
interpreter.InterpExp(values, binding_type->Expression());
interpreter.InterpExp(values, &binding_type->expression());
ExpectType(var.source_loc(), "initializer of variable", declared_type,
&var.initializer().static_type());
return;
@@ -1212,11 +1211,11 @@ void TypeChecker::TopLevel(Nonnull<Declaration*> d, TypeCheckContext* tops) {
auto& var = cast<VariableDeclaration>(*d);
// Associate the variable name with it's declared type in the
// compile-time symbol table.
Nonnull<Expression*> type =
cast<ExpressionPattern>(*var.binding().Type()).Expression();
Expression& type =
cast<ExpressionPattern>(var.binding().type()).expression();
Nonnull<const Value*> declared_type =
interpreter.InterpExp(tops->values, type);
tops->types.Set(*var.binding().Name(), declared_type);
interpreter.InterpExp(tops->values, &type);
tops->types.Set(*var.binding().name(), declared_type);
break;
}
}