Add support for return; (#678)

This creates a ReturnExpression. A separate change should enforce that an implicit return of `()` is only allowed in functions that have an implicit return type of `()`, and I think the structure taken here should ease that.
This commit is contained in:
Jon Meow
2021-08-02 16:30:08 -07:00
committed by GitHub
parent b1993a6cd0
commit 6ae9cc3cf8
16 changed files with 114 additions and 33 deletions
+8 -3
View File
@@ -100,12 +100,17 @@ auto Expression::MakeContinuationTypeLiteral(int line_num)
return type;
}
auto Expression::MakeFunctionTypeLiteral(int line_num, const Expression* param,
const Expression* ret)
auto Expression::MakeFunctionTypeLiteral(int line_num,
const Expression* parameter,
const Expression* return_type,
bool is_omitted_return_type)
-> const Expression* {
auto* t = global_arena->New<Expression>();
t->line_num = line_num;
t->value = FunctionTypeLiteral({.parameter = param, .return_type = ret});
t->value =
FunctionTypeLiteral({.parameter = parameter,
.return_type = return_type,
.is_omitted_return_type = is_omitted_return_type});
return t;
}
+4 -2
View File
@@ -124,6 +124,7 @@ struct FunctionTypeLiteral {
static constexpr ExpressionKind Kind = ExpressionKind::FunctionTypeLiteral;
const Expression* parameter;
const Expression* return_type;
bool is_omitted_return_type;
};
struct BoolTypeLiteral {
@@ -162,8 +163,9 @@ struct Expression {
static auto MakeTypeTypeLiteral(int line_num) -> const Expression*;
static auto MakeIntTypeLiteral(int line_num) -> const Expression*;
static auto MakeBoolTypeLiteral(int line_num) -> const Expression*;
static auto MakeFunctionTypeLiteral(int line_num, const Expression* param,
const Expression* ret)
static auto MakeFunctionTypeLiteral(int line_num, const Expression* parameter,
const Expression* return_type,
bool is_omitted_return_type)
-> const Expression*;
static auto MakeContinuationTypeLiteral(int line_num) -> const Expression*;
@@ -21,7 +21,10 @@ void FunctionDefinition::PrintDepth(int depth, llvm::raw_ostream& out) const {
}
out << "]";
}
out << *param_pattern << " -> " << *return_type;
out << *param_pattern;
if (!is_omitted_return_type) {
out << " -> " << *return_type;
}
if (body) {
out << " {\n";
body->PrintDepth(depth, out);
@@ -25,12 +25,14 @@ struct FunctionDefinition {
FunctionDefinition(int line_num, std::string name,
std::vector<GenericBinding> deduced_params,
const TuplePattern* param_pattern,
const Pattern* return_type, const Statement* body)
const Pattern* return_type, bool is_omitted_return_type,
const Statement* body)
: line_num(line_num),
name(std::move(name)),
deduced_parameters(deduced_params),
param_pattern(param_pattern),
return_type(return_type),
is_omitted_return_type(is_omitted_return_type),
body(body) {}
void Print(llvm::raw_ostream& out) const { PrintDepth(-1, out); }
@@ -42,6 +44,7 @@ struct FunctionDefinition {
std::vector<GenericBinding> deduced_parameters;
const TuplePattern* param_pattern;
const Pattern* return_type;
bool is_omitted_return_type;
const Statement* body;
};
+12 -4
View File
@@ -117,11 +117,15 @@ auto Statement::MakeContinue(int line_num) -> const Statement* {
return s;
}
auto Statement::MakeReturn(int line_num, const Expression* e)
-> const Statement* {
auto Statement::MakeReturn(int line_num, const Expression* exp,
bool is_omitted_exp) -> const Statement* {
auto* s = global_arena->New<Statement>();
s->line_num = line_num;
s->value = Return({.exp = e});
if (exp == nullptr) {
CHECK(is_omitted_exp);
exp = Expression::MakeTupleLiteral(line_num, {});
}
s->value = Return({.exp = exp, .is_omitted_exp = is_omitted_exp});
return s;
}
@@ -230,7 +234,11 @@ void Statement::PrintDepth(int depth, llvm::raw_ostream& out) const {
}
break;
case StatementKind::Return:
out << "return " << *GetReturn().exp << ";";
if (GetReturn().is_omitted_exp) {
out << "return;";
} else {
out << "return " << *GetReturn().exp << ";";
}
break;
case StatementKind::Sequence:
GetSequence().stmt->PrintDepth(depth, out);
+3 -1
View File
@@ -60,6 +60,7 @@ struct If {
struct Return {
static constexpr StatementKind Kind = StatementKind::Return;
const Expression* exp;
bool is_omitted_exp;
};
struct Sequence {
@@ -120,7 +121,8 @@ struct Statement {
static auto MakeIf(int line_num, const Expression* cond,
const Statement* then_stmt, const Statement* else_stmt)
-> const Statement*;
static auto MakeReturn(int line_num, const Expression* e) -> const Statement*;
static auto MakeReturn(int line_num, const Expression* exp,
bool is_omitted_exp) -> const Statement*;
static auto MakeSequence(int line_num, const Statement* s1,
const Statement* s2) -> const Statement*;
static auto MakeBlock(int line_num, const Statement* s) -> const Statement*;