Store inferred struct field type in the field node itself
This commit is contained in:
parent
ab028c9d7a
commit
53be7b92df
2 changed files with 17 additions and 24 deletions
|
|
@ -22,6 +22,7 @@ namespace pslang::ast
|
||||||
ast::type_ptr type;
|
ast::type_ptr type;
|
||||||
ast::location location;
|
ast::location location;
|
||||||
|
|
||||||
|
types::type_ptr inferred_type = nullptr;
|
||||||
field_layout layout = {};
|
field_layout layout = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,17 +30,9 @@ namespace pslang::ast
|
||||||
|
|
||||||
struct struct_data
|
struct struct_data
|
||||||
{
|
{
|
||||||
struct field_data
|
|
||||||
{
|
|
||||||
std::string name;
|
|
||||||
types::type_ptr type;
|
|
||||||
};
|
|
||||||
|
|
||||||
ast::struct_definition * node;
|
ast::struct_definition * node;
|
||||||
bool layout_being_computed = false;
|
bool layout_being_computed = false;
|
||||||
bool layout_ready = false;
|
bool layout_ready = false;
|
||||||
|
|
||||||
std::vector<field_data> fields;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct scope
|
struct scope
|
||||||
|
|
@ -115,11 +107,13 @@ namespace pslang::ast
|
||||||
if (data.layout_ready)
|
if (data.layout_ready)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
auto & struct_node = *data.node;
|
||||||
|
|
||||||
data.layout_being_computed = true;
|
data.layout_being_computed = true;
|
||||||
auto & layout = data.node->layout;
|
auto & layout = data.node->layout;
|
||||||
for (std::size_t i = 0; i < data.fields.size(); ++i)
|
for (std::size_t i = 0; i < struct_node.fields.size(); ++i)
|
||||||
{
|
{
|
||||||
auto field_layout = field_layout_visitor{{}, scopes}.apply(*data.fields[i].type);
|
auto field_layout = field_layout_visitor{{}, scopes}.apply(*struct_node.fields[i].inferred_type);
|
||||||
layout.alignment = std::max(layout.alignment, field_layout.alignment);
|
layout.alignment = std::max(layout.alignment, field_layout.alignment);
|
||||||
layout.size = ((layout.size + field_layout.alignment - 1) / field_layout.alignment) * field_layout.alignment;
|
layout.size = ((layout.size + field_layout.alignment - 1) / field_layout.alignment) * field_layout.alignment;
|
||||||
data.node->fields[i].layout.offset = layout.size;
|
data.node->fields[i].layout.offset = layout.size;
|
||||||
|
|
@ -253,20 +247,18 @@ namespace pslang::ast
|
||||||
void apply(return_statement const &)
|
void apply(return_statement const &)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void apply(field_definition const & node)
|
void apply(field_definition & node)
|
||||||
{
|
{
|
||||||
resolve_types(scopes, *node.type);
|
resolve_types(scopes, *node.type);
|
||||||
|
node.inferred_type = get_type(*node.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply(struct_definition & node)
|
void apply(struct_definition & node)
|
||||||
{
|
{
|
||||||
for (auto const & field : node.fields)
|
for (auto & field : node.fields)
|
||||||
apply(field);
|
apply(field);
|
||||||
|
|
||||||
auto & data = scopes.back().structs[node.name];
|
scopes.back().structs[node.name].node = &node;
|
||||||
data.node = &node;
|
|
||||||
for (auto const & field : node.fields)
|
|
||||||
data.fields.push_back({.name = field.name, .type = get_type(*field.type)});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -574,25 +566,25 @@ namespace pslang::ast
|
||||||
else if (auto named_type = std::get_if<types::named_type>(type.get()))
|
else if (auto named_type = std::get_if<types::named_type>(type.get()))
|
||||||
{
|
{
|
||||||
auto const & scope = scopes.at(named_type->level);
|
auto const & scope = scopes.at(named_type->level);
|
||||||
auto const & data = scope.structs.at(named_type->name);
|
auto const & struct_node = *scope.structs.at(named_type->name).node;
|
||||||
|
|
||||||
if (!node.arguments.empty())
|
if (!node.arguments.empty())
|
||||||
{
|
{
|
||||||
if (node.arguments.size() != data.fields.size())
|
if (node.arguments.size() != struct_node.fields.size())
|
||||||
{
|
{
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
os << "Cannot create struct " << named_type->name << ": expected " << data.fields.size() << " arguments, but got " << node.arguments.size();
|
os << "Cannot create struct " << named_type->name << ": expected " << struct_node.fields.size() << " arguments, but got " << node.arguments.size();
|
||||||
throw type_error(os.str(), node.location);
|
throw type_error(os.str(), node.location);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::size_t i = 0; i < node.arguments.size(); ++i)
|
for (std::size_t i = 0; i < node.arguments.size(); ++i)
|
||||||
{
|
{
|
||||||
auto arg_type = get_type(*node.arguments[i]);
|
auto arg_type = get_type(*node.arguments[i]);
|
||||||
if (!types::equal(*arg_type, *data.fields[i].type))
|
if (!types::equal(*arg_type, *struct_node.fields[i].inferred_type))
|
||||||
{
|
{
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
os << "Cannot create struct " << named_type->name << ": argument #" << i << " expected to have type ";
|
os << "Cannot create struct " << named_type->name << ": argument #" << i << " expected to have type ";
|
||||||
types::print(os, *data.fields[i].type);
|
types::print(os, *struct_node.fields[i].inferred_type);
|
||||||
os << " but got type ";
|
os << " but got type ";
|
||||||
types::print(os, *arg_type);
|
types::print(os, *arg_type);
|
||||||
throw type_error(os.str(), node.location);
|
throw type_error(os.str(), node.location);
|
||||||
|
|
@ -685,13 +677,13 @@ namespace pslang::ast
|
||||||
throw type_error(os.str(), get_location(*node.object));
|
throw type_error(os.str(), get_location(*node.object));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const & struct_data = scopes.at(named_type->level).structs.at(named_type->name);
|
auto const & struct_node = *scopes.at(named_type->level).structs.at(named_type->name).node;
|
||||||
|
|
||||||
for (auto const & field : struct_data.fields)
|
for (auto const & field : struct_node.fields)
|
||||||
{
|
{
|
||||||
if (field.name == node.field_name)
|
if (field.name == node.field_name)
|
||||||
{
|
{
|
||||||
node.inferred_type = field.type;
|
node.inferred_type = field.inferred_type;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue