|
|
@@ -39,53 +39,6 @@ void PrintTypeEnv(TypeEnv types, std::ostream& out) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// Convert tuples to tuple types.
|
|
|
-auto ToType(int line_num, const Value* val) -> const Value* {
|
|
|
- switch (val->tag) {
|
|
|
- case ValKind::TupleV: {
|
|
|
- auto fields = new VarValues();
|
|
|
- for (auto& elt : *val->u.tuple.elts) {
|
|
|
- const Value* ty = ToType(line_num, state->heap[elt.second]);
|
|
|
- fields->push_back(std::make_pair(elt.first, ty));
|
|
|
- }
|
|
|
- return MakeTupleTypeVal(fields);
|
|
|
- }
|
|
|
- case ValKind::TupleTV: {
|
|
|
- auto fields = new VarValues();
|
|
|
- for (auto& field : *val->u.tuple_type.fields) {
|
|
|
- const Value* ty = ToType(line_num, field.second);
|
|
|
- fields->push_back(std::make_pair(field.first, ty));
|
|
|
- }
|
|
|
- return MakeTupleTypeVal(fields);
|
|
|
- }
|
|
|
- case ValKind::PointerTV: {
|
|
|
- return MakePtrTypeVal(ToType(line_num, val->u.ptr_type.type));
|
|
|
- }
|
|
|
- case ValKind::FunctionTV: {
|
|
|
- return MakeFunTypeVal(ToType(line_num, val->u.fun_type.param),
|
|
|
- ToType(line_num, val->u.fun_type.ret));
|
|
|
- }
|
|
|
- case ValKind::VarPatV: {
|
|
|
- return MakeVarPatVal(*val->u.var_pat.name,
|
|
|
- ToType(line_num, val->u.var_pat.type));
|
|
|
- }
|
|
|
- case ValKind::ChoiceTV:
|
|
|
- case ValKind::StructTV:
|
|
|
- case ValKind::TypeTV:
|
|
|
- case ValKind::VarTV:
|
|
|
- case ValKind::BoolTV:
|
|
|
- case ValKind::IntTV:
|
|
|
- case ValKind::AutoTV:
|
|
|
- case ValKind::ContinuationTV:
|
|
|
- return val;
|
|
|
- default:
|
|
|
- std::cerr << line_num << ": in ToType, expected a type, not ";
|
|
|
- PrintValue(val, std::cerr);
|
|
|
- std::cerr << std::endl;
|
|
|
- exit(-1);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
// Reify type to type expression.
|
|
|
auto ReifyType(const Value* t, int line_num) -> Expression* {
|
|
|
switch (t->tag) {
|
|
|
@@ -102,11 +55,11 @@ auto ReifyType(const Value* t, int line_num) -> Expression* {
|
|
|
case ValKind::FunctionTV:
|
|
|
return MakeFunType(0, ReifyType(t->u.fun_type.param, line_num),
|
|
|
ReifyType(t->u.fun_type.ret, line_num));
|
|
|
- case ValKind::TupleTV: {
|
|
|
+ case ValKind::TupleV: {
|
|
|
auto args = new std::vector<std::pair<std::string, Expression*>>();
|
|
|
- for (auto& field : *t->u.tuple_type.fields) {
|
|
|
+ for (auto& field : *t->u.tuple.elts) {
|
|
|
args->push_back(
|
|
|
- make_pair(field.first, ReifyType(field.second, line_num)));
|
|
|
+ {field.first, ReifyType(state->heap[field.second], line_num)});
|
|
|
}
|
|
|
return MakeTuple(0, args);
|
|
|
}
|
|
|
@@ -152,8 +105,7 @@ auto TypeCheckExp(Expression* e, TypeEnv types, Env values,
|
|
|
<< std::endl;
|
|
|
exit(-1);
|
|
|
}
|
|
|
- auto t =
|
|
|
- ToType(e->line_num, InterpExp(values, e->u.pattern_variable.type));
|
|
|
+ auto t = InterpExp(values, e->u.pattern_variable.type);
|
|
|
if (t->tag == ValKind::AutoTV) {
|
|
|
if (expected == nullptr) {
|
|
|
std::cerr << e->line_num
|
|
|
@@ -174,17 +126,18 @@ auto TypeCheckExp(Expression* e, TypeEnv types, Env values,
|
|
|
TCContext::ValueContext);
|
|
|
auto t = res.type;
|
|
|
switch (t->tag) {
|
|
|
- case ValKind::TupleTV: {
|
|
|
+ case ValKind::TupleV: {
|
|
|
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) {
|
|
|
+ std::optional<Address> field_address = FindTupleField(f, t);
|
|
|
+ if (field_address == std::nullopt) {
|
|
|
std::cerr << e->line_num << ": compilation error, field " << f
|
|
|
<< " is not in the tuple ";
|
|
|
PrintValue(t, std::cerr);
|
|
|
std::cerr << std::endl;
|
|
|
exit(-1);
|
|
|
}
|
|
|
+ auto field_t = state->heap[*field_address];
|
|
|
auto new_e = MakeIndex(e->line_num, res.exp, MakeInt(e->line_num, i));
|
|
|
return TCResult(new_e, field_t, res.types);
|
|
|
}
|
|
|
@@ -196,29 +149,30 @@ auto TypeCheckExp(Expression* e, TypeEnv types, Env values,
|
|
|
}
|
|
|
case ExpressionKind::Tuple: {
|
|
|
auto new_args = new std::vector<std::pair<std::string, Expression*>>();
|
|
|
- auto arg_types = new VarValues();
|
|
|
+ auto arg_types = new std::vector<std::pair<std::string, Address>>();
|
|
|
auto new_types = types;
|
|
|
int i = 0;
|
|
|
for (auto arg = e->u.tuple.fields->begin();
|
|
|
arg != e->u.tuple.fields->end(); ++arg, ++i) {
|
|
|
const Value* arg_expected = nullptr;
|
|
|
- if (expected && expected->tag == ValKind::TupleTV) {
|
|
|
- arg_expected =
|
|
|
- FindInVarValues(arg->first, expected->u.tuple_type.fields);
|
|
|
- if (arg_expected == nullptr) {
|
|
|
+ if (expected && expected->tag == ValKind::TupleV) {
|
|
|
+ std::optional<Address> expected_field =
|
|
|
+ FindTupleField(arg->first, expected);
|
|
|
+ if (expected_field == std::nullopt) {
|
|
|
std::cerr << e->line_num << ": compilation error, missing field "
|
|
|
<< arg->first << std::endl;
|
|
|
exit(-1);
|
|
|
}
|
|
|
+ arg_expected = state->heap[*expected_field];
|
|
|
}
|
|
|
auto arg_res =
|
|
|
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));
|
|
|
+ arg_types->push_back({arg->first, AllocateValue(arg_res.type)});
|
|
|
}
|
|
|
auto tuple_e = MakeTuple(e->line_num, new_args);
|
|
|
- auto tuple_t = MakeTupleTypeVal(arg_types);
|
|
|
+ auto tuple_t = MakeTupleVal(arg_types);
|
|
|
return TCResult(tuple_e, tuple_t, new_types);
|
|
|
}
|
|
|
case ExpressionKind::GetField: {
|
|
|
@@ -247,12 +201,12 @@ auto TypeCheckExp(Expression* e, TypeEnv types, Env values,
|
|
|
<< *t->u.struct_type.name << " does not have a field named "
|
|
|
<< *e->u.get_field.field << std::endl;
|
|
|
exit(-1);
|
|
|
- case ValKind::TupleTV:
|
|
|
- for (auto& field : *t->u.tuple_type.fields) {
|
|
|
+ case ValKind::TupleV:
|
|
|
+ for (auto& field : *t->u.tuple.elts) {
|
|
|
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.types);
|
|
|
+ return TCResult(new_e, state->heap[field.second], res.types);
|
|
|
}
|
|
|
}
|
|
|
std::cerr << e->line_num << ": compilation error, struct "
|
|
|
@@ -364,10 +318,8 @@ auto TypeCheckExp(Expression* e, TypeEnv types, Env values,
|
|
|
switch (context) {
|
|
|
case TCContext::ValueContext:
|
|
|
case TCContext::TypeContext: {
|
|
|
- auto pt = ToType(e->line_num,
|
|
|
- InterpExp(values, e->u.function_type.parameter));
|
|
|
- auto rt = ToType(e->line_num,
|
|
|
- InterpExp(values, e->u.function_type.return_type));
|
|
|
+ auto pt = InterpExp(values, e->u.function_type.parameter);
|
|
|
+ auto rt = 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(), types);
|
|
|
@@ -610,7 +562,7 @@ auto TypeCheckFunDef(const FunctionDefinition* f, TypeEnv types, Env values)
|
|
|
-> struct FunctionDefinition* {
|
|
|
auto param_res = TypeCheckExp(f->param_pattern, types, values, nullptr,
|
|
|
TCContext::PatternContext);
|
|
|
- auto return_type = ToType(f->line_num, InterpExp(values, f->return_type));
|
|
|
+ auto return_type = InterpExp(values, f->return_type);
|
|
|
if (f->name == "main") {
|
|
|
ExpectType(f->line_num, "return type of `main`", MakeIntTypeVal(),
|
|
|
return_type);
|
|
|
@@ -627,13 +579,12 @@ auto TypeOfFunDef(TypeEnv types, Env values, const FunctionDefinition* fun_def)
|
|
|
-> const Value* {
|
|
|
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(values, fun_def->return_type);
|
|
|
if (ret->tag == ValKind::AutoTV) {
|
|
|
auto f = TypeCheckFunDef(fun_def, types, values);
|
|
|
ret = InterpExp(values, f->return_type);
|
|
|
}
|
|
|
- return MakeFunTypeVal(param_type, ret);
|
|
|
+ return MakeFunTypeVal(param_res.type, ret);
|
|
|
}
|
|
|
|
|
|
auto TypeOfStructDef(const StructDefinition* sd, TypeEnv /*types*/, Env ct_top)
|
|
|
@@ -642,7 +593,7 @@ auto TypeOfStructDef(const StructDefinition* sd, TypeEnv /*types*/, Env ct_top)
|
|
|
auto methods = new VarValues();
|
|
|
for (auto m = sd->members->begin(); m != sd->members->end(); ++m) {
|
|
|
if ((*m)->tag == MemberKind::FieldMember) {
|
|
|
- auto t = ToType(sd->line_num, InterpExp(ct_top, (*m)->u.field.type));
|
|
|
+ auto t = InterpExp(ct_top, (*m)->u.field.type);
|
|
|
fields->push_back(std::make_pair(*(*m)->u.field.name, t));
|
|
|
}
|
|
|
}
|
|
|
@@ -689,7 +640,7 @@ auto VariableDeclaration::TypeChecked(TypeEnv types, Env values) const
|
|
|
-> Declaration {
|
|
|
TCResult type_checked_initializer = TypeCheckExp(
|
|
|
initializer, types, values, nullptr, TCContext::ValueContext);
|
|
|
- const Value* declared_type = ToType(source_location, InterpExp(values, type));
|
|
|
+ const Value* declared_type = InterpExp(values, type);
|
|
|
ExpectType(source_location, "initializer of variable", declared_type,
|
|
|
type_checked_initializer.type);
|
|
|
return *this;
|
|
|
@@ -723,15 +674,18 @@ auto StructDeclaration::TopLevel(TypeCheckContext& tops) const -> void {
|
|
|
auto st = TypeOfStructDef(&definition, tops.types, tops.values);
|
|
|
Address a = AllocateValue(st);
|
|
|
tops.values.Set(Name(), a); // Is this obsolete?
|
|
|
- auto params = MakeTupleTypeVal(st->u.struct_type.fields);
|
|
|
- auto fun_ty = MakeFunTypeVal(params, st);
|
|
|
+ auto field_types = new std::vector<std::pair<std::string, Address>>();
|
|
|
+ for (const auto& [field_name, field_value] : *st->u.struct_type.fields) {
|
|
|
+ field_types->push_back({field_name, AllocateValue(field_value)});
|
|
|
+ }
|
|
|
+ auto fun_ty = MakeFunTypeVal(MakeTupleVal(field_types), st);
|
|
|
tops.types.Set(Name(), fun_ty);
|
|
|
}
|
|
|
|
|
|
auto ChoiceDeclaration::TopLevel(TypeCheckContext& tops) const -> void {
|
|
|
auto alts = new VarValues();
|
|
|
for (auto a : alternatives) {
|
|
|
- auto t = ToType(line_num, InterpExp(tops.values, a.second));
|
|
|
+ auto t = InterpExp(tops.values, a.second);
|
|
|
alts->push_back(std::make_pair(a.first, t));
|
|
|
}
|
|
|
auto ct = MakeChoiceTypeVal(name, alts);
|
|
|
@@ -743,8 +697,7 @@ auto ChoiceDeclaration::TopLevel(TypeCheckContext& tops) const -> void {
|
|
|
// Associate the variable name with it's declared type in the
|
|
|
// compile-time symbol table.
|
|
|
auto VariableDeclaration::TopLevel(TypeCheckContext& tops) const -> void {
|
|
|
- const Value* declared_type =
|
|
|
- ToType(source_location, InterpExp(tops.values, type));
|
|
|
+ const Value* declared_type = InterpExp(tops.values, type);
|
|
|
tops.types.Set(Name(), declared_type);
|
|
|
}
|
|
|
|