Adds basic support for class functions and methods. (#1057)

* adding methods to the ast

* pre commit stuff?

* implementation of class functions

* implemented methods

* some cleanup

* more cleanup

* add newlines in test programs

* pre-commit fixups

* added include of return_term.h

* a test of a method calling another method

* replacing Member with Declaration

* removing the member.h etc files

* clarify a type annotation

* update uses of FunctionDeclaration

* remove ReturnTarget, no longer needed

* more cleanup

* more cleanup

* yet more cleanup, playing with pre-commit

* did a pre-commit run --all-files

* fixed const issue

* remove comment

* checking dependencies in BUILD files and headers

* pre-commit working now

* refactor NominalClassType to just hold a pointer to the class declaration

* remove Member from rtti

* responding to Geoffreys review

* change field_types to a non-member function
This commit is contained in:
Jeremy G. Siek
2022-02-05 12:30:13 -05:00
committed by GitHub
parent 4479c55305
commit ac0b810bf3
27 changed files with 739 additions and 351 deletions
@@ -316,9 +316,11 @@ void Interpreter::StepLvalue() {
}
}
case ExpressionKind::PrimitiveOperatorExpression: {
const PrimitiveOperatorExpression& op = cast<PrimitiveOperatorExpression>(exp);
const PrimitiveOperatorExpression& op =
cast<PrimitiveOperatorExpression>(exp);
if (op.op() != Operator::Deref) {
FATAL() << "Can't treat primitive operator expression as lvalue: " << exp;
FATAL() << "Can't treat primitive operator expression as lvalue: "
<< exp;
}
if (act.pos() == 0) {
return todo_.Spawn(
@@ -355,6 +357,7 @@ auto Interpreter::Convert(Nonnull<const Value*> value,
switch (value->kind()) {
case Value::Kind::IntValue:
case Value::Kind::FunctionValue:
case Value::Kind::BoundMethodValue:
case Value::Kind::PointerValue:
case Value::Kind::LValue:
case Value::Kind::BoolValue:
@@ -573,6 +576,23 @@ void Interpreter::StepExp() {
std::make_unique<StatementAction>(*function.body()),
std::move(function_scope));
}
case Value::Kind::BoundMethodValue: {
const BoundMethodValue& m =
cast<BoundMethodValue>(*act.results()[0]);
const FunctionDeclaration& method = m.declaration();
Nonnull<const Value*> converted_args = Convert(
act.results()[1], &method.param_pattern().static_type());
RuntimeScope method_scope(&heap_);
CHECK(PatternMatch(&method.me_pattern().value(), m.receiver(),
exp.source_loc(), &method_scope));
CHECK(PatternMatch(&method.param_pattern().value(), converted_args,
exp.source_loc(), &method_scope));
CHECK(method.body().has_value())
<< "Calling a method that's missing a body";
return todo_.Spawn(
std::make_unique<StatementAction>(*method.body()),
std::move(method_scope));
}
default:
FATAL_RUNTIME_ERROR(exp.source_loc())
<< "in call, expected a function, not " << *act.results()[0];
@@ -928,11 +948,15 @@ void Interpreter::StepDeclaration() {
switch (decl.kind()) {
case DeclarationKind::VariableDeclaration: {
const auto& var_decl = cast<VariableDeclaration>(decl);
if (act.pos() == 0) {
return todo_.Spawn(
std::make_unique<ExpressionAction>(&var_decl.initializer()));
if (var_decl.has_initializer()) {
if (act.pos() == 0) {
return todo_.Spawn(
std::make_unique<ExpressionAction>(&var_decl.initializer()));
} else {
todo_.Initialize(&var_decl.binding(), act.results()[0]);
return todo_.FinishAction();
}
} else {
todo_.Initialize(&var_decl.binding(), act.results()[0]);
return todo_.FinishAction();
}
}