Convert Pattern and Expression to Ptr (#787)

Sorry about the big change, this is hard to split. ParenContents is used by both, templated, and expects the same pointer type. While I could duplicate ParenContents with some ExpressionParenContents or PatternParenContents, that seems a little kludgy versus a single large change handling both. The worst of it is that Expression is already pretty sweeping, Pattern is really just incrementally adding.

That said, I believe this includes a couple fixes I found with incorrect use of dyn_cast in typecheck.cpp (checked nullptr at the wrong step in 2 code locations). There's also a missing `*` in member.cpp this caught. I adjust passing of expressions for Return due to nullness (I felt adding another constructor was the best solution).

I add a `.Release()` to BisonWrap due to things like `$3.first` needing some way to work through BIsonWrap. I felt this was better than `operator->`, but feel free to comment if you prefer the other path (`.Release()` conveniently lets me do pair unwrapping, so it felt a better solution).

I do add a TODO to think about better Ptr-to-Ptr cast<> support too, though, as that doesn't work cleanly with LLVM's infra. But so far it seems to only come up in one spot, so I'm not prioritizing it.
This commit is contained in:
Jon Meow
2021-08-27 09:16:20 -07:00
committed by GitHub
parent e93a361032
commit fd89bcb4aa
21 changed files with 394 additions and 375 deletions
+9 -9
View File
@@ -72,47 +72,47 @@ class Action {
class LValAction : public Action {
public:
explicit LValAction(const Expression* exp)
explicit LValAction(Ptr<const Expression> exp)
: Action(Kind::LValAction), exp(exp) {}
static auto classof(const Action* action) -> bool {
return action->Tag() == Kind::LValAction;
}
auto Exp() const -> const Expression* { return exp; }
auto Exp() const -> Ptr<const Expression> { return exp; }
private:
const Expression* exp;
Ptr<const Expression> exp;
};
class ExpressionAction : public Action {
public:
explicit ExpressionAction(const Expression* exp)
explicit ExpressionAction(Ptr<const Expression> exp)
: Action(Kind::ExpressionAction), exp(exp) {}
static auto classof(const Action* action) -> bool {
return action->Tag() == Kind::ExpressionAction;
}
auto Exp() const -> const Expression* { return exp; }
auto Exp() const -> Ptr<const Expression> { return exp; }
private:
const Expression* exp;
Ptr<const Expression> exp;
};
class PatternAction : public Action {
public:
explicit PatternAction(const Pattern* pat)
explicit PatternAction(Ptr<const Pattern> pat)
: Action(Kind::PatternAction), pat(pat) {}
static auto classof(const Action* action) -> bool {
return action->Tag() == Kind::PatternAction;
}
auto Pat() const -> const Pattern* { return pat; }
auto Pat() const -> Ptr<const Pattern> { return pat; }
private:
const Pattern* pat;
Ptr<const Pattern> pat;
};
class StatementAction : public Action {
@@ -142,9 +142,9 @@ void InitEnv(const Declaration& d, Env* env) {
for (Ptr<const Member> m : class_def.members) {
switch (m->Tag()) {
case Member::Kind::FieldMember: {
const BindingPattern* binding = cast<FieldMember>(*m).Binding();
const Expression* type_expression =
cast<ExpressionPattern>(binding->Type())->Expression();
Ptr<const BindingPattern> binding = cast<FieldMember>(*m).Binding();
Ptr<const Expression> type_expression =
cast<ExpressionPattern>(*binding->Type()).Expression();
auto type = InterpExp(Env(), type_expression);
fields.push_back(make_pair(*binding->Name(), type));
break;
@@ -205,7 +205,7 @@ void DeallocateLocals(Ptr<Frame> frame) {
}
}
const Value* CreateTuple(Ptr<Action> act, const Expression* exp) {
const Value* CreateTuple(Ptr<Action> act, Ptr<const Expression> exp) {
// { { (v1,...,vn) :: C, E, F} :: S, H}
// -> { { `(v1,...,vn) :: C, E, F} :: S, H}
const auto& tup_lit = cast<TupleLiteral>(*exp);
@@ -431,7 +431,7 @@ using Transition =
// State transitions for lvalues.
Transition StepLvalue() {
Ptr<Action> act = state->stack.Top()->todo.Top();
const Expression* exp = cast<LValAction>(*act).Exp();
Ptr<const Expression> exp = cast<LValAction>(*act).Exp();
if (tracing_output) {
llvm::outs() << "--- step lvalue " << *exp << " --->\n";
}
@@ -483,7 +483,8 @@ Transition StepLvalue() {
if (act->Pos() == 0) {
// { {(f1=e1,...) :: C, E, F} :: S, H}
// -> { {e1 :: (f1=[],...) :: C, E, F} :: S, H}
const Expression* e1 = cast<TupleLiteral>(*exp).Fields()[0].expression;
Ptr<const Expression> e1 =
cast<TupleLiteral>(*exp).Fields()[0].expression;
return Spawn{global_arena->New<LValAction>(e1)};
} else if (act->Pos() !=
static_cast<int>(cast<TupleLiteral>(*exp).Fields().size())) {
@@ -491,7 +492,7 @@ Transition StepLvalue() {
// H}
// -> { { ek+1 :: (f1=v1,..., fk=vk, fk+1=[],...) :: C, E, F} :: S,
// H}
const Expression* elt =
Ptr<const Expression> elt =
cast<TupleLiteral>(*exp).Fields()[act->Pos()].expression;
return Spawn{global_arena->New<LValAction>(elt)};
} else {
@@ -518,7 +519,7 @@ Transition StepLvalue() {
// State transitions for expressions.
Transition StepExp() {
Ptr<Action> act = state->stack.Top()->todo.Top();
const Expression* exp = cast<ExpressionAction>(*act).Exp();
Ptr<const Expression> exp = cast<ExpressionAction>(*act).Exp();
if (tracing_output) {
llvm::outs() << "--- step exp " << *exp << " --->\n";
}
@@ -555,7 +556,7 @@ Transition StepExp() {
if (cast<TupleLiteral>(*exp).Fields().size() > 0) {
// { {(f1=e1,...) :: C, E, F} :: S, H}
// -> { {e1 :: (f1=[],...) :: C, E, F} :: S, H}
const Expression* e1 =
Ptr<const Expression> e1 =
cast<TupleLiteral>(*exp).Fields()[0].expression;
return Spawn{global_arena->New<ExpressionAction>(e1)};
} else {
@@ -567,7 +568,7 @@ Transition StepExp() {
// H}
// -> { { ek+1 :: (f1=v1,..., fk=vk, fk+1=[],...) :: C, E, F} :: S,
// H}
const Expression* elt =
Ptr<const Expression> elt =
cast<TupleLiteral>(*exp).Fields()[act->Pos()].expression;
return Spawn{global_arena->New<ExpressionAction>(elt)};
} else {
@@ -608,7 +609,7 @@ Transition StepExp() {
if (act->Pos() != static_cast<int>(op.Arguments().size())) {
// { {v :: op(vs,[],e,es) :: C, E, F} :: S, H}
// -> { {e :: op(vs,v,[],es) :: C, E, F} :: S, H}
const Expression* arg = op.Arguments()[act->Pos()];
Ptr<const Expression> arg = op.Arguments()[act->Pos()];
return Spawn{global_arena->New<ExpressionAction>(arg)};
} else {
// { {v :: op(vs,[]) :: C, E, F} :: S, H}
@@ -715,7 +716,7 @@ Transition StepExp() {
Transition StepPattern() {
Ptr<Action> act = state->stack.Top()->todo.Top();
const Pattern* pattern = cast<PatternAction>(*act).Pat();
Ptr<const Pattern> pattern = cast<PatternAction>(*act).Pat();
if (tracing_output) {
llvm::outs() << "--- step pattern " << *pattern << " --->\n";
}
@@ -739,7 +740,7 @@ Transition StepPattern() {
if (tuple.Fields().empty()) {
return Done{&TupleValue::Empty()};
} else {
const Pattern* p1 = tuple.Fields()[0].pattern;
Ptr<const Pattern> p1 = tuple.Fields()[0].pattern;
return Spawn{(global_arena->New<PatternAction>(p1))};
}
} else if (act->Pos() != static_cast<int>(tuple.Fields().size())) {
@@ -747,7 +748,7 @@ Transition StepPattern() {
// H}
// -> { { ek+1 :: (f1=v1,..., fk=vk, fk+1=[],...) :: C, E, F} :: S,
// H}
const Pattern* elt = tuple.Fields()[act->Pos()].pattern;
Ptr<const Pattern> elt = tuple.Fields()[act->Pos()].pattern;
return Spawn{global_arena->New<PatternAction>(elt)};
} else {
std::vector<TupleElement> elements;
@@ -775,7 +776,7 @@ Transition StepPattern() {
}
case Pattern::Kind::ExpressionPattern:
return Delegate{global_arena->New<ExpressionAction>(
cast<ExpressionPattern>(pattern)->Expression())};
cast<ExpressionPattern>(*pattern).Expression())};
}
}
@@ -1045,8 +1046,7 @@ Transition StepStmt() {
Stack<Ptr<Scope>>(global_arena->New<Scope>(CurrentEnv(state)));
Stack<Ptr<Action>> todo;
todo.Push(global_arena->New<StatementAction>(
global_arena->RawNew<Return>(stmt->SourceLoc(), nullptr,
/*is_omitted_exp=*/true)));
global_arena->RawNew<Return>(stmt->SourceLoc())));
todo.Push(
global_arena->New<StatementAction>(cast<Continuation>(*stmt).Body()));
auto continuation_frame =
@@ -1076,7 +1076,7 @@ Transition StepStmt() {
auto ignore_result = global_arena->New<StatementAction>(
global_arena->RawNew<ExpressionStatement>(
stmt->SourceLoc(),
global_arena->RawNew<TupleLiteral>(stmt->SourceLoc())));
global_arena->New<TupleLiteral>(stmt->SourceLoc())));
frame->todo.Push(ignore_result);
// Push the continuation onto the current stack.
const std::vector<Ptr<Frame>>& continuation_vector =
@@ -1217,9 +1217,9 @@ auto InterpProgram(const std::list<Ptr<const Declaration>>& fs) -> int {
SourceLocation loc("<InterpProgram()>", 0);
const Expression* arg = global_arena->RawNew<TupleLiteral>(loc);
const Expression* call_main = global_arena->RawNew<CallExpression>(
loc, global_arena->RawNew<IdentifierExpression>(loc, "main"), arg);
Ptr<const Expression> arg = global_arena->New<TupleLiteral>(loc);
Ptr<const Expression> call_main = global_arena->New<CallExpression>(
loc, global_arena->New<IdentifierExpression>(loc, "main"), arg);
auto todo =
Stack<Ptr<Action>>(global_arena->New<ExpressionAction>(call_main));
auto scopes = Stack<Ptr<Scope>>(global_arena->New<Scope>(globals));
@@ -1241,7 +1241,7 @@ auto InterpProgram(const std::list<Ptr<const Declaration>>& fs) -> int {
}
// Interpret an expression at compile-time.
auto InterpExp(Env values, const Expression* e) -> const Value* {
auto InterpExp(Env values, Ptr<const Expression> e) -> const Value* {
CHECK(state->program_value == std::nullopt);
auto program_value_guard =
llvm::make_scope_exit([] { state->program_value = std::nullopt; });
@@ -1258,7 +1258,7 @@ auto InterpExp(Env values, const Expression* e) -> const Value* {
}
// Interpret a pattern at compile-time.
auto InterpPattern(Env values, const Pattern* p) -> const Value* {
auto InterpPattern(Env values, Ptr<const Pattern> p) -> const Value* {
CHECK(state->program_value == std::nullopt);
auto program_value_guard =
llvm::make_scope_exit([] { state->program_value = std::nullopt; });
@@ -43,8 +43,8 @@ auto PatternMatch(const Value* p, const Value* v, SourceLocation loc)
-> std::optional<Env>;
auto InterpProgram(const std::list<Ptr<const Declaration>>& fs) -> int;
auto InterpExp(Env values, const Expression* e) -> const Value*;
auto InterpPattern(Env values, const Pattern* p) -> const Value*;
auto InterpExp(Env values, Ptr<const Expression> e) -> const Value*;
auto InterpPattern(Env values, Ptr<const Pattern> p) -> const Value*;
} // namespace Carbon
+62 -62
View File
@@ -55,20 +55,20 @@ static SourceLocation ReifyFakeSourceLoc() {
}
// Reify type to type expression.
static auto ReifyType(const Value* t, SourceLocation loc) -> const Expression* {
static auto ReifyType(const Value* t, SourceLocation loc)
-> Ptr<const Expression> {
switch (t->Tag()) {
case Value::Kind::IntType:
return global_arena->RawNew<IntTypeLiteral>(ReifyFakeSourceLoc());
return global_arena->New<IntTypeLiteral>(ReifyFakeSourceLoc());
case Value::Kind::BoolType:
return global_arena->RawNew<BoolTypeLiteral>(ReifyFakeSourceLoc());
return global_arena->New<BoolTypeLiteral>(ReifyFakeSourceLoc());
case Value::Kind::TypeType:
return global_arena->RawNew<TypeTypeLiteral>(ReifyFakeSourceLoc());
return global_arena->New<TypeTypeLiteral>(ReifyFakeSourceLoc());
case Value::Kind::ContinuationType:
return global_arena->RawNew<ContinuationTypeLiteral>(
ReifyFakeSourceLoc());
return global_arena->New<ContinuationTypeLiteral>(ReifyFakeSourceLoc());
case Value::Kind::FunctionType: {
const auto& fn_type = cast<FunctionType>(*t);
return global_arena->RawNew<FunctionTypeLiteral>(
return global_arena->New<FunctionTypeLiteral>(
ReifyFakeSourceLoc(), ReifyType(fn_type.Param(), loc),
ReifyType(fn_type.Ret(), loc),
/*is_omitted_return_type=*/false);
@@ -79,24 +79,24 @@ static auto ReifyType(const Value* t, SourceLocation loc) -> const Expression* {
args.push_back(
FieldInitializer(field.name, ReifyType(field.value, loc)));
}
return global_arena->RawNew<TupleLiteral>(ReifyFakeSourceLoc(), args);
return global_arena->New<TupleLiteral>(ReifyFakeSourceLoc(), args);
}
case Value::Kind::ClassType:
return global_arena->RawNew<IdentifierExpression>(
return global_arena->New<IdentifierExpression>(
ReifyFakeSourceLoc(), cast<ClassType>(*t).Name());
case Value::Kind::ChoiceType:
return global_arena->RawNew<IdentifierExpression>(
return global_arena->New<IdentifierExpression>(
ReifyFakeSourceLoc(), cast<ChoiceType>(*t).Name());
case Value::Kind::PointerType:
return global_arena->RawNew<PrimitiveOperatorExpression>(
return global_arena->New<PrimitiveOperatorExpression>(
ReifyFakeSourceLoc(), Operator::Ptr,
std::vector<const Expression*>(
std::vector<Ptr<const Expression>>(
{ReifyType(cast<PointerType>(*t).Type(), loc)}));
case Value::Kind::VariableType:
return global_arena->RawNew<IdentifierExpression>(
return global_arena->New<IdentifierExpression>(
ReifyFakeSourceLoc(), cast<VariableType>(*t).Name());
case Value::Kind::StringType:
return global_arena->RawNew<StringTypeLiteral>(ReifyFakeSourceLoc());
return global_arena->New<StringTypeLiteral>(ReifyFakeSourceLoc());
case Value::Kind::AlternativeConstructorValue:
case Value::Kind::AlternativeValue:
case Value::Kind::AutoType:
@@ -266,7 +266,7 @@ static auto Substitute(TypeEnv dict, const Value* type) -> const Value* {
// types maps variable names to the type of their run-time value.
// values maps variable names to their compile-time values. It is not
// directly used in this function but is passed to InterExp.
auto TypeCheckExp(const Expression* e, TypeEnv types, Env values)
auto TypeCheckExp(Ptr<const Expression> e, TypeEnv types, Env values)
-> TCExpression {
if (tracing_output) {
llvm::outs() << "checking expression " << *e << "\ntypes: ";
@@ -289,9 +289,9 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values)
FATAL_COMPILATION_ERROR(e->SourceLoc())
<< "field " << f << " is not in the tuple " << *t;
}
auto new_e = global_arena->RawNew<IndexExpression>(
auto new_e = global_arena->New<IndexExpression>(
e->SourceLoc(), res.exp,
global_arena->RawNew<IntLiteral>(e->SourceLoc(), i));
global_arena->New<IntLiteral>(e->SourceLoc(), i));
return TCExpression(new_e, field_t, res.types);
}
default:
@@ -308,8 +308,7 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values)
new_args.push_back(FieldInitializer(arg.name, arg_res.exp));
arg_types.push_back({.name = arg.name, .value = arg_res.type});
}
auto tuple_e =
global_arena->RawNew<TupleLiteral>(e->SourceLoc(), new_args);
auto tuple_e = global_arena->New<TupleLiteral>(e->SourceLoc(), new_args);
auto tuple_t = global_arena->RawNew<TupleValue>(std::move(arg_types));
return TCExpression(tuple_e, tuple_t, new_types);
}
@@ -323,8 +322,8 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values)
// Search for a field
for (auto& field : t_class.Fields()) {
if (access.Field() == field.first) {
const Expression* new_e =
global_arena->RawNew<FieldAccessExpression>(
Ptr<const Expression> new_e =
global_arena->New<FieldAccessExpression>(
e->SourceLoc(), res.exp, access.Field());
return TCExpression(new_e, field.second, res.types);
}
@@ -332,8 +331,8 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values)
// Search for a method
for (auto& method : t_class.Methods()) {
if (access.Field() == method.first) {
const Expression* new_e =
global_arena->RawNew<FieldAccessExpression>(
Ptr<const Expression> new_e =
global_arena->New<FieldAccessExpression>(
e->SourceLoc(), res.exp, access.Field());
return TCExpression(new_e, method.second, res.types);
}
@@ -346,7 +345,7 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values)
const auto& tup = cast<TupleValue>(*t);
for (const TupleElement& field : tup.Elements()) {
if (access.Field() == field.name) {
auto new_e = global_arena->RawNew<FieldAccessExpression>(
auto new_e = global_arena->New<FieldAccessExpression>(
e->SourceLoc(), res.exp, access.Field());
return TCExpression(new_e, field.value, res.types);
}
@@ -359,8 +358,8 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values)
const auto& choice = cast<ChoiceType>(*t);
for (const auto& vt : choice.Alternatives()) {
if (access.Field() == vt.first) {
const Expression* new_e =
global_arena->RawNew<FieldAccessExpression>(
Ptr<const Expression> new_e =
global_arena->New<FieldAccessExpression>(
e->SourceLoc(), res.exp, access.Field());
auto fun_ty = global_arena->RawNew<FunctionType>(
std::vector<GenericBinding>(), vt.second, t);
@@ -393,16 +392,16 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values)
return TCExpression(e, global_arena->RawNew<BoolType>(), types);
case Expression::Kind::PrimitiveOperatorExpression: {
const auto& op = cast<PrimitiveOperatorExpression>(*e);
std::vector<const Expression*> es;
std::vector<Ptr<const Expression>> es;
std::vector<const Value*> ts;
auto new_types = types;
for (const Expression* argument : op.Arguments()) {
for (Ptr<const Expression> argument : op.Arguments()) {
auto res = TypeCheckExp(argument, types, values);
new_types = res.types;
es.push_back(res.exp);
ts.push_back(res.type);
}
auto new_e = global_arena->RawNew<PrimitiveOperatorExpression>(
auto new_e = global_arena->New<PrimitiveOperatorExpression>(
e->SourceLoc(), op.Op(), es);
switch (op.Op()) {
case Operator::Neg:
@@ -492,7 +491,7 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values)
} else {
ExpectType(e->SourceLoc(), "call", parameter_type, arg_res.type);
}
auto new_e = global_arena->RawNew<CallExpression>(
auto new_e = global_arena->New<CallExpression>(
e->SourceLoc(), fun_res.exp, arg_res.exp);
return TCExpression(new_e, return_type, arg_res.types);
}
@@ -508,7 +507,7 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values)
const auto& fn = cast<FunctionTypeLiteral>(*e);
auto pt = InterpExp(values, fn.Parameter());
auto rt = InterpExp(values, fn.ReturnType());
auto new_e = global_arena->RawNew<FunctionTypeLiteral>(
auto new_e = global_arena->New<FunctionTypeLiteral>(
e->SourceLoc(), ReifyType(pt, e->SourceLoc()),
ReifyType(rt, e->SourceLoc()),
/*is_omitted_return_type=*/false);
@@ -533,7 +532,7 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values)
// Equivalent to TypeCheckExp, but operates on Patterns instead of Expressions.
// `expected` is the type that this pattern is expected to have, if the
// surrounding context gives us that information. Otherwise, it is null.
auto TypeCheckPattern(const Pattern* p, TypeEnv types, Env values,
auto TypeCheckPattern(Ptr<const Pattern> p, TypeEnv types, Env values,
const Value* expected) -> TCPattern {
if (tracing_output) {
llvm::outs() << "checking pattern " << *p;
@@ -569,9 +568,9 @@ auto TypeCheckPattern(const Pattern* p, TypeEnv types, Env values,
<< "Name bindings within type patterns are unsupported";
type = expected;
}
auto new_p = global_arena->RawNew<BindingPattern>(
auto new_p = global_arena->New<BindingPattern>(
binding.SourceLoc(), binding.Name(),
global_arena->RawNew<ExpressionPattern>(
global_arena->New<ExpressionPattern>(
ReifyType(type, binding.SourceLoc())));
if (binding.Name().has_value()) {
types.Set(*binding.Name(), type);
@@ -612,7 +611,7 @@ auto TypeCheckPattern(const Pattern* p, TypeEnv types, Env values,
field_types.push_back({.name = field.name, .value = field_result.type});
}
auto new_tuple =
global_arena->RawNew<TuplePattern>(tuple.SourceLoc(), new_fields);
global_arena->New<TuplePattern>(tuple.SourceLoc(), new_fields);
auto tuple_t = global_arena->RawNew<TupleValue>(std::move(field_types));
return {.pattern = new_tuple, .type = tuple_t, .types = new_types};
}
@@ -637,28 +636,30 @@ auto TypeCheckPattern(const Pattern* p, TypeEnv types, Env values,
}
TCPattern arg_results = TypeCheckPattern(alternative.Arguments(), types,
values, parameter_types);
return {.pattern = global_arena->RawNew<AlternativePattern>(
// TODO: Think about a cleaner way to cast between Ptr types.
auto arguments = Ptr<const TuplePattern>(
cast<const TuplePattern>(arg_results.pattern.Get()));
return {.pattern = global_arena->New<AlternativePattern>(
alternative.SourceLoc(),
ReifyType(choice_type, alternative.SourceLoc()),
alternative.AlternativeName(),
cast<TuplePattern>(arg_results.pattern)),
alternative.AlternativeName(), arguments),
.type = choice_type,
.types = arg_results.types};
}
case Pattern::Kind::ExpressionPattern: {
TCExpression result =
TypeCheckExp(cast<ExpressionPattern>(p)->Expression(), types, values);
return {.pattern = global_arena->RawNew<ExpressionPattern>(result.exp),
TypeCheckExp(cast<ExpressionPattern>(*p).Expression(), types, values);
return {.pattern = global_arena->New<ExpressionPattern>(result.exp),
.type = result.type,
.types = result.types};
}
}
}
static auto TypecheckCase(const Value* expected, const Pattern* pat,
static auto TypecheckCase(const Value* expected, Ptr<const Pattern> pat,
const Statement* body, TypeEnv types, Env values,
const Value*& ret_type, bool is_omitted_ret_type)
-> std::pair<const Pattern*, const Statement*> {
-> std::pair<Ptr<const Pattern>, const Statement*> {
auto pat_res = TypeCheckPattern(pat, types, values, expected);
auto res =
TypeCheckStmt(body, pat_res.types, values, ret_type, is_omitted_ret_type);
@@ -684,7 +685,7 @@ auto TypeCheckStmt(const Statement* s, TypeEnv types, Env values,
auto res = TypeCheckExp(match.Exp(), types, values);
auto res_type = res.type;
auto new_clauses = global_arena->RawNew<
std::list<std::pair<const Pattern*, const Statement*>>>();
std::list<std::pair<Ptr<const Pattern>, const Statement*>>>();
for (auto& clause : *match.Clauses()) {
new_clauses->push_back(TypecheckCase(res_type, clause.first,
clause.second, types, values,
@@ -817,8 +818,7 @@ static auto CheckOrEnsureReturn(const Statement* stmt, bool omitted_ret_type,
SourceLocation loc) -> const Statement* {
if (!stmt) {
if (omitted_ret_type) {
return global_arena->RawNew<Return>(loc, nullptr,
/*is_omitted_exp=*/true);
return global_arena->RawNew<Return>(loc);
} else {
FATAL_COMPILATION_ERROR(loc)
<< "control-flow reaches end of function that provides a `->` return "
@@ -829,7 +829,7 @@ static auto CheckOrEnsureReturn(const Statement* stmt, bool omitted_ret_type,
case Statement::Kind::Match: {
const auto& match = cast<Match>(*stmt);
auto new_clauses = global_arena->RawNew<
std::list<std::pair<const Pattern*, const Statement*>>>();
std::list<std::pair<Ptr<const Pattern>, const Statement*>>>();
for (const auto& clause : *match.Clauses()) {
auto s = CheckOrEnsureReturn(clause.second, omitted_ret_type,
stmt->SourceLoc());
@@ -878,9 +878,7 @@ static auto CheckOrEnsureReturn(const Statement* stmt, bool omitted_ret_type,
case Statement::Kind::VariableDefinition:
if (omitted_ret_type) {
return global_arena->RawNew<Sequence>(
stmt->SourceLoc(), stmt,
global_arena->RawNew<Return>(loc, nullptr,
/*is_omitted_exp=*/true));
stmt->SourceLoc(), stmt, global_arena->RawNew<Return>(loc));
} else {
FATAL_COMPILATION_ERROR(stmt->SourceLoc())
<< "control-flow reaches end of function that provides a `->` "
@@ -917,7 +915,7 @@ static auto TypeCheckFunDef(const FunctionDefinition* f, TypeEnv types,
f->source_location);
return global_arena->New<FunctionDefinition>(
f->source_location, f->name, f->deduced_parameters, f->param_pattern,
global_arena->RawNew<ExpressionPattern>(
global_arena->New<ExpressionPattern>(
ReifyType(return_type, f->source_location)),
/*is_omitted_return_type=*/false, body);
}
@@ -951,18 +949,18 @@ static auto TypeOfClassDef(const ClassDefinition* sd, TypeEnv /*types*/,
for (Ptr<const Member> m : sd->members) {
switch (m->Tag()) {
case Member::Kind::FieldMember: {
const BindingPattern* binding = cast<FieldMember>(*m).Binding();
Ptr<const BindingPattern> binding = cast<FieldMember>(*m).Binding();
if (!binding->Name().has_value()) {
FATAL_COMPILATION_ERROR(binding->SourceLoc())
<< "Struct members must have names";
}
const Expression* type_expression =
dyn_cast<ExpressionPattern>(binding->Type())->Expression();
if (type_expression == nullptr) {
const auto* binding_type =
dyn_cast<ExpressionPattern>(binding->Type().Get());
if (binding_type == nullptr) {
FATAL_COMPILATION_ERROR(binding->SourceLoc())
<< "Struct members must have explicit types";
}
auto type = InterpExp(ct_top, type_expression);
auto type = InterpExp(ct_top, binding_type->Expression());
fields.push_back(std::make_pair(*binding->Name(), type));
break;
}
@@ -981,7 +979,8 @@ static auto GetName(const Declaration& d) -> const std::string& {
case Declaration::Kind::ChoiceDeclaration:
return cast<ChoiceDeclaration>(d).Name();
case Declaration::Kind::VariableDeclaration: {
const BindingPattern* binding = cast<VariableDeclaration>(d).Binding();
Ptr<const BindingPattern> binding =
cast<VariableDeclaration>(d).Binding();
if (!binding->Name().has_value()) {
FATAL_COMPILATION_ERROR(binding->SourceLoc())
<< "Top-level variable declarations must have names";
@@ -1025,14 +1024,15 @@ auto MakeTypeChecked(const Ptr<const Declaration> d, const TypeEnv& types,
// declaration with annotated types.
TCExpression type_checked_initializer =
TypeCheckExp(var.Initializer(), types, values);
const Expression* type =
dyn_cast<ExpressionPattern>(var.Binding()->Type())->Expression();
if (type == nullptr) {
const auto* binding_type =
dyn_cast<ExpressionPattern>(var.Binding()->Type().Get());
if (binding_type == nullptr) {
// TODO: consider adding support for `auto`
FATAL_COMPILATION_ERROR(var.SourceLoc())
<< "Type of a top-level variable must be an expression.";
}
const Value* declared_type = InterpExp(values, type);
const Value* declared_type =
InterpExp(values, binding_type->Expression());
ExpectType(var.SourceLoc(), "initializer of variable", declared_type,
type_checked_initializer.type);
return d;
@@ -1087,8 +1087,8 @@ static void TopLevel(const Declaration& d, TypeCheckContext* tops) {
const auto& var = cast<VariableDeclaration>(d);
// Associate the variable name with it's declared type in the
// compile-time symbol table.
const Expression* type =
cast<ExpressionPattern>(var.Binding()->Type())->Expression();
Ptr<const Expression> type =
cast<ExpressionPattern>(*var.Binding()->Type()).Expression();
const Value* declared_type = InterpExp(tops->values, type);
tops->types.Set(*var.Binding()->Name(), declared_type);
break;
+5 -5
View File
@@ -19,16 +19,16 @@ namespace Carbon {
using TypeEnv = Dictionary<std::string, const Value*>;
struct TCExpression {
TCExpression(const Expression* e, const Value* t, TypeEnv types)
TCExpression(Ptr<const Expression> e, const Value* t, TypeEnv types)
: exp(e), type(t), types(types) {}
const Expression* exp;
Ptr<const Expression> exp;
const Value* type;
TypeEnv types;
};
struct TCPattern {
const Pattern* pattern;
Ptr<const Pattern> pattern;
const Value* type;
TypeEnv types;
};
@@ -47,9 +47,9 @@ struct TypeCheckContext {
Env values;
};
auto TypeCheckExp(const Expression* e, TypeEnv types, Env values)
auto TypeCheckExp(Ptr<const Expression> e, TypeEnv types, Env values)
-> TCExpression;
auto TypeCheckPattern(const Pattern* p, TypeEnv types, Env values,
auto TypeCheckPattern(Ptr<const Pattern> p, TypeEnv types, Env values,
const Value* expected) -> TCPattern;
auto TypeCheckStmt(const Statement* s, TypeEnv types, Env values,