rename env and ct_env (#419)

* change env to types, ct_env to values in type checker, change env to values in interpreter

* fix bazeliskrc, change to use latest (#420)
This commit is contained in:
Jeremy G. Siek
2021-03-30 13:41:24 -04:00
committed by GitHub
parent c7b93c4477
commit 3d02412f2f
4 changed files with 168 additions and 163 deletions
@@ -154,8 +154,8 @@ void KillObject(Address address) {
}
}
void PrintEnv(Env env, std::ostream& out) {
for (const auto& [name, value] : env) {
void PrintEnv(Env values, std::ostream& out) {
for (const auto& [name, value] : values) {
out << name << ": ";
PrintValue(state->heap[value], out);
out << ", ";
@@ -196,7 +196,7 @@ void PrintHeap(const std::vector<const Value*>& heap, std::ostream& out) {
auto CurrentEnv(State* state) -> Env {
Frame* frame = state->stack.Top();
return frame->scopes.Top()->env;
return frame->scopes.Top()->values;
}
void PrintState(std::ostream& out) {
@@ -206,7 +206,7 @@ void PrintState(std::ostream& out) {
out << std::endl << "heap: ";
PrintHeap(state->heap, out);
if (!state->stack.IsEmpty() && !state->stack.Top()->scopes.IsEmpty()) {
out << std::endl << "env: ";
out << std::endl << "values: ";
PrintEnv(CurrentEnv(state), out);
}
out << std::endl << "}" << std::endl;
@@ -328,8 +328,8 @@ auto StructDeclaration::InitGlobals(Env& globals) const -> void {
}
auto FunctionDeclaration::InitGlobals(Env& globals) const -> void {
Env env;
auto pt = InterpExp(env, definition->param_pattern);
Env values;
auto pt = InterpExp(values, definition->param_pattern);
auto f = MakeFunVal(definition->name, pt, definition->body);
Address a = AllocateValue(f);
globals.Set(definition->name, a);
@@ -353,15 +353,15 @@ void CallFunction(int line_num, std::vector<const Value*> operas,
case ValKind::FunV: {
// Bind arguments to parameters
std::list<std::string> params;
std::optional<Env> env_with_matches = PatternMatch(
std::optional<Env> matches = PatternMatch(
operas[0]->u.fun.param, operas[1], globals, &params, line_num);
if (!env_with_matches) {
if (!matches) {
std::cerr << "internal error in call_function, pattern match failed"
<< std::endl;
exit(-1);
}
// Create the new frame and push it on the stack
auto* scope = new Scope(*env_with_matches, params);
auto* scope = new Scope(*matches, params);
auto* frame = new Frame(*operas[0]->u.fun.name, Stack(scope),
Stack(MakeStmtAct(operas[0]->u.fun.body)));
state->stack.Push(frame);
@@ -393,7 +393,7 @@ void CallFunction(int line_num, std::vector<const Value*> operas,
void KillScope(int line_num, Scope* scope) {
for (const auto& l : scope->locals) {
std::optional<Address> a = scope->env.Get(l);
std::optional<Address> a = scope->values.Get(l);
if (!a) {
std::cerr << "internal error in KillScope" << std::endl;
exit(-1);
@@ -427,15 +427,15 @@ void CreateTuple(Frame* frame, Action* act, Expression* /*exp*/) {
//
// The names of the pattern variables are added to the vars parameter.
// Returns nullopt if the value doesn't match the pattern.
auto PatternMatch(const Value* p, const Value* v, Env env,
auto PatternMatch(const Value* p, const Value* v, Env values,
std::list<std::string>* vars, int line_num)
-> std::optional<Env> {
switch (p->tag) {
case ValKind::VarPatV: {
Address a = AllocateValue(CopyVal(v, line_num));
vars->push_back(*p->u.var_pat.name);
env.Set(*p->u.var_pat.name, a);
return env;
values.Set(*p->u.var_pat.name, a);
return values;
}
case ValKind::TupleV:
switch (v->tag) {
@@ -453,14 +453,15 @@ auto PatternMatch(const Value* p, const Value* v, Env env,
std::cerr << std::endl;
exit(-1);
}
std::optional<Env> env_with_matches = PatternMatch(
state->heap[elt.second], state->heap[*a], env, vars, line_num);
if (!env_with_matches) {
std::optional<Env> matches =
PatternMatch(state->heap[elt.second], state->heap[*a], values,
vars, line_num);
if (!matches) {
return std::nullopt;
}
env = *env_with_matches;
values = *matches;
} // for
return env;
return values;
}
default:
std::cerr
@@ -476,13 +477,13 @@ auto PatternMatch(const Value* p, const Value* v, Env env,
*p->u.alt.alt_name != *v->u.alt.alt_name) {
return std::nullopt;
}
std::optional<Env> env_with_matches =
PatternMatch(state->heap[p->u.alt.argument],
state->heap[v->u.alt.argument], env, vars, line_num);
if (!env_with_matches) {
std::optional<Env> matches = PatternMatch(
state->heap[p->u.alt.argument], state->heap[v->u.alt.argument],
values, vars, line_num);
if (!matches) {
return std::nullopt;
}
return *env_with_matches;
return *matches;
}
default:
std::cerr
@@ -495,20 +496,20 @@ auto PatternMatch(const Value* p, const Value* v, Env env,
case ValKind::FunctionTV:
switch (v->tag) {
case ValKind::FunctionTV: {
std::optional<Env> env_with_matches = PatternMatch(
p->u.fun_type.param, v->u.fun_type.param, env, vars, line_num);
if (!env_with_matches) {
std::optional<Env> matches = PatternMatch(
p->u.fun_type.param, v->u.fun_type.param, values, vars, line_num);
if (!matches) {
return std::nullopt;
}
return PatternMatch(p->u.fun_type.ret, v->u.fun_type.ret,
*env_with_matches, vars, line_num);
return PatternMatch(p->u.fun_type.ret, v->u.fun_type.ret, *matches,
vars, line_num);
}
default:
return std::nullopt;
}
default:
if (ValueEqual(p, v, line_num)) {
return env;
return values;
} else {
return std::nullopt;
}
@@ -925,8 +926,8 @@ void StepStmt() {
// Store the continuation's address in the frame.
continuation_frame->continuation = continuation_address;
// Bind the continuation object to the continuation variable
frame->scopes.Top()->env.Set(*stmt->u.continuation.continuation_variable,
continuation_address);
frame->scopes.Top()->values.Set(
*stmt->u.continuation.continuation_variable, continuation_address);
// Pop the continuation statement.
frame->todo.Pop();
break;
@@ -1249,17 +1250,17 @@ void HandleValue() {
const Value* v = act->results[0];
const Value* p = act->results[1];
std::optional<Env> env_with_matches =
PatternMatch(p, v, frame->scopes.Top()->env,
std::optional<Env> matches =
PatternMatch(p, v, frame->scopes.Top()->values,
&frame->scopes.Top()->locals, stmt->line_num);
if (!env_with_matches) {
if (!matches) {
std::cerr
<< stmt->line_num
<< ": internal error in variable definition, match failed"
<< std::endl;
exit(-1);
}
frame->scopes.Top()->env = *env_with_matches;
frame->scopes.Top()->values = *matches;
frame->todo.Pop(2);
}
break;
@@ -1341,12 +1342,12 @@ void HandleValue() {
} else { // try to match
auto v = act->results[0];
auto pat = act->results[clause_num + 1];
auto env = CurrentEnv(state);
auto values = CurrentEnv(state);
std::list<std::string> vars;
std::optional<Env> env_with_matches =
PatternMatch(pat, v, env, &vars, stmt->line_num);
if (env_with_matches) { // we have a match, start the body
auto* new_scope = new Scope(*env_with_matches, vars);
std::optional<Env> matches =
PatternMatch(pat, v, values, &vars, stmt->line_num);
if (matches) { // we have a match, start the body
auto* new_scope = new Scope(*matches, vars);
frame->scopes.Push(new_scope);
Statement* body_block = MakeBlock(stmt->line_num, c->second);
Action* body_act = MakeStmtAct(body_block);
@@ -1486,9 +1487,9 @@ auto InterpProgram(std::list<Declaration>* fs) -> int {
}
// Interpret an expression at compile-time.
auto InterpExp(Env env, Expression* e) -> const Value* {
auto InterpExp(Env values, Expression* e) -> const Value* {
auto todo = Stack(MakeExpAct(e));
auto* scope = new Scope(env, std::list<std::string>());
auto* scope = new Scope(values, std::list<std::string>());
auto* frame = new Frame("InterpExp", Stack(scope), todo);
state->stack = Stack(frame);
@@ -22,8 +22,9 @@ using Env = Dictionary<std::string, Address>;
/***** Scopes *****/
struct Scope {
Scope(Env e, std::list<std::string> l) : env(e), locals(std::move(l)) {}
Env env;
Scope(Env values, std::list<std::string> l)
: values(values), locals(std::move(l)) {}
Env values;
std::list<std::string> locals;
};
@@ -68,7 +69,7 @@ extern State* state;
auto PrintFrame(Frame* frame, std::ostream& out) -> void;
void PrintStack(Stack<Frame*> ls, std::ostream& out);
void PrintEnv(Env env);
void PrintEnv(Env values);
auto AllocateValue(const Value* v) -> Address;
auto CopyVal(const Value* val, int line_num) -> const Value*;
auto ToInteger(const Value* v) -> int;
@@ -76,7 +77,7 @@ auto ToInteger(const Value* v) -> int;
/***** Interpreters *****/
auto InterpProgram(std::list<Declaration>* fs) -> int;
auto InterpExp(Env env, Expression* e) -> const Value*;
auto InterpExp(Env values, Expression* e) -> const Value*;
} // namespace Carbon
+112 -109
View File
@@ -31,8 +31,8 @@ void ExpectType(int line_num, const std::string& context, const Value* expected,
void PrintErrorString(const std::string& s) { std::cerr << s; }
void PrintTypeEnv(TypeEnv env, std::ostream& out) {
for (const auto& [name, value] : env) {
void PrintTypeEnv(TypeEnv types, std::ostream& out) {
for (const auto& [name, value] : types) {
out << name << ": ";
PrintValue(value, out);
out << ", ";
@@ -132,16 +132,16 @@ auto ReifyType(const Value* t, int line_num) -> Expression* {
// generic.
//
// e is the expression to be analyzed.
// env maps variable names to the type of their run-time value.
// ct_env maps variable names to their compile-time values. It is not
// 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.
// expected is the type that this expression is expected to have.
// This parameter is non-null when the expression is in a pattern context
// and it is used to implement `auto`, otherwise it is null.
// context says what kind of position this expression is nested in,
// whether it's a position that expects a value, a pattern, or a type.
auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, const Value* expected,
TCContext context) -> TCResult {
auto TypeCheckExp(Expression* e, TypeEnv types, Env values,
const Value* expected, TCContext context) -> TCResult {
switch (e->tag) {
case ExpressionKind::PatternVariable: {
if (context != TCContext::PatternContext) {
@@ -153,7 +153,7 @@ auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, const Value* expected,
exit(-1);
}
auto t =
ToType(e->line_num, InterpExp(ct_env, e->u.pattern_variable.type));
ToType(e->line_num, InterpExp(values, e->u.pattern_variable.type));
if (t->tag == ValKind::AutoTV) {
if (expected == nullptr) {
std::cerr << e->line_num
@@ -166,16 +166,16 @@ auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, const Value* expected,
}
auto new_e = MakeVarPat(e->line_num, *e->u.pattern_variable.name,
ReifyType(t, e->line_num));
env.Set(*e->u.pattern_variable.name, t);
return TCResult(new_e, t, env);
types.Set(*e->u.pattern_variable.name, t);
return TCResult(new_e, t, types);
}
case ExpressionKind::Index: {
auto res = TypeCheckExp(e->u.get_field.aggregate, env, ct_env, nullptr,
auto res = TypeCheckExp(e->u.get_field.aggregate, types, values, nullptr,
TCContext::ValueContext);
auto t = res.type;
switch (t->tag) {
case ValKind::TupleTV: {
auto i = ToInteger(InterpExp(ct_env, e->u.index.offset));
auto i = ToInteger(InterpExp(values, e->u.index.offset));
std::string f = std::to_string(i);
auto field_t = FindInVarValues(f, t->u.tuple_type.fields);
if (field_t == nullptr) {
@@ -186,7 +186,7 @@ auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, const Value* expected,
exit(-1);
}
auto new_e = MakeIndex(e->line_num, res.exp, MakeInt(e->line_num, i));
return TCResult(new_e, field_t, res.env);
return TCResult(new_e, field_t, res.types);
}
default:
std::cerr << e->line_num << ": compilation error, expected a tuple"
@@ -197,7 +197,7 @@ auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, const Value* expected,
case ExpressionKind::Tuple: {
auto new_args = new std::vector<std::pair<std::string, Expression*>>();
auto arg_types = new VarValues();
auto new_env = env;
auto new_types = types;
int i = 0;
for (auto arg = e->u.tuple.fields->begin();
arg != e->u.tuple.fields->end(); ++arg, ++i) {
@@ -212,17 +212,17 @@ auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, const Value* expected,
}
}
auto arg_res =
TypeCheckExp(arg->second, new_env, ct_env, arg_expected, context);
new_env = arg_res.env;
TypeCheckExp(arg->second, new_types, values, arg_expected, context);
new_types = arg_res.types;
new_args->push_back(std::make_pair(arg->first, arg_res.exp));
arg_types->push_back(std::make_pair(arg->first, arg_res.type));
}
auto tuple_e = MakeTuple(e->line_num, new_args);
auto tuple_t = MakeTupleTypeVal(arg_types);
return TCResult(tuple_e, tuple_t, new_env);
return TCResult(tuple_e, tuple_t, new_types);
}
case ExpressionKind::GetField: {
auto res = TypeCheckExp(e->u.get_field.aggregate, env, ct_env, nullptr,
auto res = TypeCheckExp(e->u.get_field.aggregate, types, values, nullptr,
TCContext::ValueContext);
auto t = res.type;
switch (t->tag) {
@@ -232,7 +232,7 @@ auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, const Value* expected,
if (*e->u.get_field.field == field.first) {
Expression* new_e =
MakeGetField(e->line_num, res.exp, *e->u.get_field.field);
return TCResult(new_e, field.second, res.env);
return TCResult(new_e, field.second, res.types);
}
}
// Search for a method
@@ -240,7 +240,7 @@ auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, const Value* expected,
if (*e->u.get_field.field == method.first) {
Expression* new_e =
MakeGetField(e->line_num, res.exp, *e->u.get_field.field);
return TCResult(new_e, method.second, res.env);
return TCResult(new_e, method.second, res.types);
}
}
std::cerr << e->line_num << ": compilation error, struct "
@@ -252,7 +252,7 @@ auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, const Value* expected,
if (*e->u.get_field.field == field.first) {
auto new_e =
MakeGetField(e->line_num, res.exp, *e->u.get_field.field);
return TCResult(new_e, field.second, res.env);
return TCResult(new_e, field.second, res.types);
}
}
std::cerr << e->line_num << ": compilation error, struct "
@@ -266,7 +266,7 @@ auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, const Value* expected,
Expression* new_e =
MakeGetField(e->line_num, res.exp, *e->u.get_field.field);
auto fun_ty = MakeFunTypeVal(vt->second, t);
return TCResult(new_e, fun_ty, res.env);
return TCResult(new_e, fun_ty, res.types);
}
}
std::cerr << e->line_num << ": compilation error, struct "
@@ -284,9 +284,9 @@ auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, const Value* expected,
}
}
case ExpressionKind::Variable: {
std::optional<const Value*> type = env.Get(*(e->u.variable.name));
std::optional<const Value*> type = types.Get(*(e->u.variable.name));
if (type) {
return TCResult(e, *type, env);
return TCResult(e, *type, types);
} else {
std::cerr << e->line_num << ": could not find `"
<< *(e->u.variable.name) << "`" << std::endl;
@@ -294,17 +294,17 @@ auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, const Value* expected,
}
}
case ExpressionKind::Integer:
return TCResult(e, MakeIntTypeVal(), env);
return TCResult(e, MakeIntTypeVal(), types);
case ExpressionKind::Boolean:
return TCResult(e, MakeBoolTypeVal(), env);
return TCResult(e, MakeBoolTypeVal(), types);
case ExpressionKind::PrimitiveOp: {
auto es = new std::vector<Expression*>();
std::vector<const Value*> ts;
auto new_env = env;
auto new_types = types;
for (auto& argument : *e->u.primitive_op.arguments) {
auto res = TypeCheckExp(argument, env, ct_env, nullptr,
auto res = TypeCheckExp(argument, types, values, nullptr,
TCContext::ValueContext);
new_env = res.env;
new_types = res.types;
es->push_back(res.exp);
ts.push_back(res.type);
}
@@ -312,42 +312,42 @@ auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, const Value* expected,
switch (e->u.primitive_op.op) {
case Operator::Neg:
ExpectType(e->line_num, "negation", MakeIntTypeVal(), ts[0]);
return TCResult(new_e, MakeIntTypeVal(), new_env);
return TCResult(new_e, MakeIntTypeVal(), new_types);
case Operator::Add:
case Operator::Sub:
ExpectType(e->line_num, "subtraction(1)", MakeIntTypeVal(), ts[0]);
ExpectType(e->line_num, "substration(2)", MakeIntTypeVal(), ts[1]);
return TCResult(new_e, MakeIntTypeVal(), new_env);
return TCResult(new_e, MakeIntTypeVal(), new_types);
case Operator::And:
ExpectType(e->line_num, "&&(1)", MakeBoolTypeVal(), ts[0]);
ExpectType(e->line_num, "&&(2)", MakeBoolTypeVal(), ts[1]);
return TCResult(new_e, MakeBoolTypeVal(), new_env);
return TCResult(new_e, MakeBoolTypeVal(), new_types);
case Operator::Or:
ExpectType(e->line_num, "||(1)", MakeBoolTypeVal(), ts[0]);
ExpectType(e->line_num, "||(2)", MakeBoolTypeVal(), ts[1]);
return TCResult(new_e, MakeBoolTypeVal(), new_env);
return TCResult(new_e, MakeBoolTypeVal(), new_types);
case Operator::Not:
ExpectType(e->line_num, "!", MakeBoolTypeVal(), ts[0]);
return TCResult(new_e, MakeBoolTypeVal(), new_env);
return TCResult(new_e, MakeBoolTypeVal(), new_types);
case Operator::Eq:
ExpectType(e->line_num, "==(1)", MakeIntTypeVal(), ts[0]);
ExpectType(e->line_num, "==(2)", MakeIntTypeVal(), ts[1]);
return TCResult(new_e, MakeBoolTypeVal(), new_env);
return TCResult(new_e, MakeBoolTypeVal(), new_types);
}
break;
}
case ExpressionKind::Call: {
auto fun_res = TypeCheckExp(e->u.call.function, env, ct_env, nullptr,
auto fun_res = TypeCheckExp(e->u.call.function, types, values, nullptr,
TCContext::ValueContext);
switch (fun_res.type->tag) {
case ValKind::FunctionTV: {
auto fun_t = fun_res.type;
auto arg_res = TypeCheckExp(e->u.call.argument, fun_res.env, ct_env,
auto arg_res = TypeCheckExp(e->u.call.argument, fun_res.types, values,
fun_t->u.fun_type.param, context);
ExpectType(e->line_num, "call", fun_t->u.fun_type.param,
arg_res.type);
auto new_e = MakeCall(e->line_num, fun_res.exp, arg_res.exp);
return TCResult(new_e, fun_t->u.fun_type.ret, arg_res.env);
return TCResult(new_e, fun_t->u.fun_type.ret, arg_res.types);
}
default: {
std::cerr << e->line_num
@@ -365,44 +365,45 @@ auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, const Value* expected,
case TCContext::ValueContext:
case TCContext::TypeContext: {
auto pt = ToType(e->line_num,
InterpExp(ct_env, e->u.function_type.parameter));
InterpExp(values, e->u.function_type.parameter));
auto rt = ToType(e->line_num,
InterpExp(ct_env, e->u.function_type.return_type));
InterpExp(values, e->u.function_type.return_type));
auto new_e = MakeFunType(e->line_num, ReifyType(pt, e->line_num),
ReifyType(rt, e->line_num));
return TCResult(new_e, MakeTypeTypeVal(), env);
return TCResult(new_e, MakeTypeTypeVal(), types);
}
case TCContext::PatternContext: {
auto param_res = TypeCheckExp(e->u.function_type.parameter, env,
ct_env, nullptr, context);
auto ret_res = TypeCheckExp(e->u.function_type.return_type,
param_res.env, ct_env, nullptr, context);
auto param_res = TypeCheckExp(e->u.function_type.parameter, types,
values, nullptr, context);
auto ret_res =
TypeCheckExp(e->u.function_type.return_type, param_res.types,
values, nullptr, context);
auto new_e =
MakeFunType(e->line_num, ReifyType(param_res.type, e->line_num),
ReifyType(ret_res.type, e->line_num));
return TCResult(new_e, MakeTypeTypeVal(), ret_res.env);
return TCResult(new_e, MakeTypeTypeVal(), ret_res.types);
}
}
}
case ExpressionKind::IntT:
return TCResult(e, MakeIntTypeVal(), env);
return TCResult(e, MakeIntTypeVal(), types);
case ExpressionKind::BoolT:
return TCResult(e, MakeBoolTypeVal(), env);
return TCResult(e, MakeBoolTypeVal(), types);
case ExpressionKind::TypeT:
return TCResult(e, MakeTypeTypeVal(), env);
return TCResult(e, MakeTypeTypeVal(), types);
case ExpressionKind::AutoT:
return TCResult(e, MakeAutoTypeVal(), env);
return TCResult(e, MakeAutoTypeVal(), types);
case ExpressionKind::ContinuationT:
return TCResult(e, MakeContinuationTypeVal(), env);
return TCResult(e, MakeContinuationTypeVal(), types);
}
}
auto TypecheckCase(const Value* expected, Expression* pat, Statement* body,
TypeEnv env, Env ct_env, const Value*& ret_type)
TypeEnv types, Env values, const Value*& ret_type)
-> std::pair<Expression*, Statement*> {
auto pat_res =
TypeCheckExp(pat, env, ct_env, expected, TCContext::PatternContext);
auto res = TypeCheckStmt(body, pat_res.env, ct_env, ret_type);
TypeCheckExp(pat, types, values, expected, TCContext::PatternContext);
auto res = TypeCheckStmt(body, pat_res.types, values, ret_type);
return std::make_pair(pat, res.stmt);
}
@@ -413,90 +414,92 @@ auto TypecheckCase(const Value* expected, Expression* pat, Statement* body,
// It is the declared return type of the enclosing function definition.
// If the return type is "auto", then the return type is inferred from
// the first return statement.
auto TypeCheckStmt(Statement* s, TypeEnv env, Env ct_env,
auto TypeCheckStmt(Statement* s, TypeEnv types, Env values,
const Value*& ret_type) -> TCStatement {
if (!s) {
return TCStatement(s, env);
return TCStatement(s, types);
}
switch (s->tag) {
case StatementKind::Match: {
auto res = TypeCheckExp(s->u.match_stmt.exp, env, ct_env, nullptr,
auto res = TypeCheckExp(s->u.match_stmt.exp, types, values, nullptr,
TCContext::ValueContext);
auto res_type = res.type;
auto new_clauses = new std::list<std::pair<Expression*, Statement*>>();
for (auto& clause : *s->u.match_stmt.clauses) {
new_clauses->push_back(TypecheckCase(
res_type, clause.first, clause.second, env, ct_env, ret_type));
res_type, clause.first, clause.second, types, values, ret_type));
}
Statement* new_s = MakeMatch(s->line_num, res.exp, new_clauses);
return TCStatement(new_s, env);
return TCStatement(new_s, types);
}
case StatementKind::While: {
auto cnd_res = TypeCheckExp(s->u.while_stmt.cond, env, ct_env, nullptr,
auto cnd_res = TypeCheckExp(s->u.while_stmt.cond, types, values, nullptr,
TCContext::ValueContext);
ExpectType(s->line_num, "condition of `while`", MakeBoolTypeVal(),
cnd_res.type);
auto body_res =
TypeCheckStmt(s->u.while_stmt.body, env, ct_env, ret_type);
TypeCheckStmt(s->u.while_stmt.body, types, values, ret_type);
auto new_s = MakeWhile(s->line_num, cnd_res.exp, body_res.stmt);
return TCStatement(new_s, env);
return TCStatement(new_s, types);
}
case StatementKind::Break:
case StatementKind::Continue:
return TCStatement(s, env);
return TCStatement(s, types);
case StatementKind::Block: {
auto stmt_res = TypeCheckStmt(s->u.block.stmt, env, ct_env, ret_type);
return TCStatement(MakeBlock(s->line_num, stmt_res.stmt), env);
auto stmt_res = TypeCheckStmt(s->u.block.stmt, types, values, ret_type);
return TCStatement(MakeBlock(s->line_num, stmt_res.stmt), types);
}
case StatementKind::VariableDefinition: {
auto res = TypeCheckExp(s->u.variable_definition.init, env, ct_env,
auto res = TypeCheckExp(s->u.variable_definition.init, types, values,
nullptr, TCContext::ValueContext);
const Value* rhs_ty = res.type;
auto lhs_res = TypeCheckExp(s->u.variable_definition.pat, env, ct_env,
auto lhs_res = TypeCheckExp(s->u.variable_definition.pat, types, values,
rhs_ty, TCContext::PatternContext);
Statement* new_s =
MakeVarDef(s->line_num, s->u.variable_definition.pat, res.exp);
return TCStatement(new_s, lhs_res.env);
return TCStatement(new_s, lhs_res.types);
}
case StatementKind::Sequence: {
auto stmt_res = TypeCheckStmt(s->u.sequence.stmt, env, ct_env, ret_type);
auto env2 = stmt_res.env;
auto next_res = TypeCheckStmt(s->u.sequence.next, env2, ct_env, ret_type);
auto env3 = next_res.env;
auto stmt_res =
TypeCheckStmt(s->u.sequence.stmt, types, values, ret_type);
auto types2 = stmt_res.types;
auto next_res =
TypeCheckStmt(s->u.sequence.next, types2, values, ret_type);
auto types3 = next_res.types;
return TCStatement(MakeSeq(s->line_num, stmt_res.stmt, next_res.stmt),
env3);
types3);
}
case StatementKind::Assign: {
auto rhs_res = TypeCheckExp(s->u.assign.rhs, env, ct_env, nullptr,
auto rhs_res = TypeCheckExp(s->u.assign.rhs, types, values, nullptr,
TCContext::ValueContext);
auto rhs_t = rhs_res.type;
auto lhs_res = TypeCheckExp(s->u.assign.lhs, env, ct_env, rhs_t,
auto lhs_res = TypeCheckExp(s->u.assign.lhs, types, values, rhs_t,
TCContext::ValueContext);
auto lhs_t = lhs_res.type;
ExpectType(s->line_num, "assign", lhs_t, rhs_t);
auto new_s = MakeAssign(s->line_num, lhs_res.exp, rhs_res.exp);
return TCStatement(new_s, lhs_res.env);
return TCStatement(new_s, lhs_res.types);
}
case StatementKind::ExpressionStatement: {
auto res =
TypeCheckExp(s->u.exp, env, ct_env, nullptr, TCContext::ValueContext);
auto res = TypeCheckExp(s->u.exp, types, values, nullptr,
TCContext::ValueContext);
auto new_s = MakeExpStmt(s->line_num, res.exp);
return TCStatement(new_s, env);
return TCStatement(new_s, types);
}
case StatementKind::If: {
auto cnd_res = TypeCheckExp(s->u.if_stmt.cond, env, ct_env, nullptr,
auto cnd_res = TypeCheckExp(s->u.if_stmt.cond, types, values, nullptr,
TCContext::ValueContext);
ExpectType(s->line_num, "condition of `if`", MakeBoolTypeVal(),
cnd_res.type);
auto thn_res =
TypeCheckStmt(s->u.if_stmt.then_stmt, env, ct_env, ret_type);
TypeCheckStmt(s->u.if_stmt.then_stmt, types, values, ret_type);
auto els_res =
TypeCheckStmt(s->u.if_stmt.else_stmt, env, ct_env, ret_type);
TypeCheckStmt(s->u.if_stmt.else_stmt, types, values, ret_type);
auto new_s = MakeIf(s->line_num, cnd_res.exp, thn_res.stmt, els_res.stmt);
return TCStatement(new_s, env);
return TCStatement(new_s, types);
}
case StatementKind::Return: {
auto res = TypeCheckExp(s->u.return_stmt, env, ct_env, nullptr,
auto res = TypeCheckExp(s->u.return_stmt, types, values, nullptr,
TCContext::ValueContext);
if (ret_type->tag == ValKind::AutoTV) {
// The following infers the return type from the first 'return'
@@ -506,29 +509,29 @@ auto TypeCheckStmt(Statement* s, TypeEnv env, Env ct_env,
} else {
ExpectType(s->line_num, "return", ret_type, res.type);
}
return TCStatement(MakeReturn(s->line_num, res.exp), env);
return TCStatement(MakeReturn(s->line_num, res.exp), types);
}
case StatementKind::Continuation: {
TCStatement body_result =
TypeCheckStmt(s->u.continuation.body, env, ct_env, ret_type);
TypeCheckStmt(s->u.continuation.body, types, values, ret_type);
Statement* new_continuation = MakeContinuationStatement(
s->line_num, *s->u.continuation.continuation_variable,
body_result.stmt);
env.Set(*s->u.continuation.continuation_variable,
MakeContinuationTypeVal());
return TCStatement(new_continuation, env);
types.Set(*s->u.continuation.continuation_variable,
MakeContinuationTypeVal());
return TCStatement(new_continuation, types);
}
case StatementKind::Run: {
TCResult argument_result = TypeCheckExp(s->u.run.argument, env, ct_env,
TCResult argument_result = TypeCheckExp(s->u.run.argument, types, values,
nullptr, TCContext::ValueContext);
ExpectType(s->line_num, "argument of `run`", MakeContinuationTypeVal(),
argument_result.type);
Statement* new_run = MakeRun(s->line_num, argument_result.exp);
return TCStatement(new_run, env);
return TCStatement(new_run, types);
}
case StatementKind::Await: {
// nothing to do here
return TCStatement(s, env);
return TCStatement(s, types);
}
} // switch
}
@@ -603,37 +606,37 @@ auto CheckOrEnsureReturn(Statement* stmt, bool void_return, int line_num)
}
}
auto TypeCheckFunDef(const FunctionDefinition* f, TypeEnv env, Env ct_env)
auto TypeCheckFunDef(const FunctionDefinition* f, TypeEnv types, Env values)
-> struct FunctionDefinition* {
auto param_res = TypeCheckExp(f->param_pattern, env, ct_env, nullptr,
auto param_res = TypeCheckExp(f->param_pattern, types, values, nullptr,
TCContext::PatternContext);
auto return_type = ToType(f->line_num, InterpExp(ct_env, f->return_type));
auto return_type = ToType(f->line_num, InterpExp(values, f->return_type));
if (f->name == "main") {
ExpectType(f->line_num, "return type of `main`", MakeIntTypeVal(),
return_type);
// TODO: Check that main doesn't have any parameters.
}
auto res = TypeCheckStmt(f->body, param_res.env, ct_env, return_type);
auto res = TypeCheckStmt(f->body, param_res.types, values, return_type);
bool void_return = TypeEqual(return_type, MakeVoidTypeVal());
auto body = CheckOrEnsureReturn(res.stmt, void_return, f->line_num);
return MakeFunDef(f->line_num, f->name, ReifyType(return_type, f->line_num),
f->param_pattern, body);
}
auto TypeOfFunDef(TypeEnv env, Env ct_env, const FunctionDefinition* fun_def)
auto TypeOfFunDef(TypeEnv types, Env values, const FunctionDefinition* fun_def)
-> const Value* {
auto param_res = TypeCheckExp(fun_def->param_pattern, env, ct_env, nullptr,
auto param_res = TypeCheckExp(fun_def->param_pattern, types, values, nullptr,
TCContext::PatternContext);
auto param_type = ToType(fun_def->line_num, param_res.type);
auto ret = InterpExp(ct_env, fun_def->return_type);
auto ret = InterpExp(values, fun_def->return_type);
if (ret->tag == ValKind::AutoTV) {
auto f = TypeCheckFunDef(fun_def, env, ct_env);
ret = InterpExp(ct_env, f->return_type);
auto f = TypeCheckFunDef(fun_def, types, values);
ret = InterpExp(values, f->return_type);
}
return MakeFunTypeVal(param_type, ret);
}
auto TypeOfStructDef(const StructDefinition* sd, TypeEnv /*env*/, Env ct_top)
auto TypeOfStructDef(const StructDefinition* sd, TypeEnv /*types*/, Env ct_top)
-> const Value* {
auto fields = new VarValues();
auto methods = new VarValues();
@@ -657,7 +660,7 @@ auto ChoiceDeclaration::Name() const -> std::string { return name; }
// Returns the name of the declared variable.
auto VariableDeclaration::Name() const -> std::string { return name; }
auto StructDeclaration::TypeChecked(TypeEnv env, Env ct_env) const
auto StructDeclaration::TypeChecked(TypeEnv types, Env values) const
-> Declaration {
auto fields = new std::list<Member*>();
for (auto& m : *definition.members) {
@@ -669,12 +672,12 @@ auto StructDeclaration::TypeChecked(TypeEnv env, Env ct_env) const
return StructDeclaration(definition.line_num, *definition.name, fields);
}
auto FunctionDeclaration::TypeChecked(TypeEnv env, Env ct_env) const
auto FunctionDeclaration::TypeChecked(TypeEnv types, Env values) const
-> Declaration {
return FunctionDeclaration(TypeCheckFunDef(definition, env, ct_env));
return FunctionDeclaration(TypeCheckFunDef(definition, types, values));
}
auto ChoiceDeclaration::TypeChecked(TypeEnv env, Env ct_env) const
auto ChoiceDeclaration::TypeChecked(TypeEnv types, Env values) const
-> Declaration {
return *this; // TODO.
}
@@ -682,11 +685,11 @@ auto ChoiceDeclaration::TypeChecked(TypeEnv env, Env ct_env) const
// Signals a type error if the initializing expression does not have
// the declared type of the variable, otherwise returns this
// declaration with annotated types.
auto VariableDeclaration::TypeChecked(TypeEnv env, Env ct_env) const
auto VariableDeclaration::TypeChecked(TypeEnv types, Env values) const
-> Declaration {
TCResult type_checked_initializer =
TypeCheckExp(initializer, env, ct_env, nullptr, TCContext::ValueContext);
const Value* declared_type = ToType(source_location, InterpExp(ct_env, type));
TCResult type_checked_initializer = TypeCheckExp(
initializer, types, values, nullptr, TCContext::ValueContext);
const Value* declared_type = ToType(source_location, InterpExp(values, type));
ExpectType(source_location, "initializer of variable", declared_type,
type_checked_initializer.type);
return *this;
+8 -8
View File
@@ -16,30 +16,30 @@ namespace Carbon {
using TypeEnv = Dictionary<std::string, const Value*>;
void PrintTypeEnv(TypeEnv env);
void PrintTypeEnv(TypeEnv types);
enum class TCContext { ValueContext, PatternContext, TypeContext };
struct TCResult {
TCResult(Expression* e, const Value* t, TypeEnv env)
: exp(e), type(t), env(env) {}
TCResult(Expression* e, const Value* t, TypeEnv types)
: exp(e), type(t), types(types) {}
Expression* exp;
const Value* type;
TypeEnv env;
TypeEnv types;
};
struct TCStatement {
TCStatement(Statement* s, TypeEnv e) : stmt(s), env(e) {}
TCStatement(Statement* s, TypeEnv types) : stmt(s), types(types) {}
Statement* stmt;
TypeEnv env;
TypeEnv types;
};
auto ToType(int line_num, const Value* val) -> const Value*;
auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, const Value* expected,
TCContext context) -> TCResult;
auto TypeCheckExp(Expression* e, TypeEnv types, Env values,
const Value* expected, TCContext context) -> TCResult;
auto TypeCheckStmt(Statement*, TypeEnv, Env, Value const*&) -> TCStatement;