aboutsummaryrefslogtreecommitdiffstats
path: root/AST.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'AST.cpp')
-rw-r--r--AST.cpp36
1 files changed, 35 insertions, 1 deletions
diff --git a/AST.cpp b/AST.cpp
index 9aecbded..22a658d4 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -51,6 +51,40 @@ void StructDefinition::accept(ASTVisitor& _visitor)
_visitor.endVisit(*this);
}
+void StructDefinition::checkValidityOfMembers()
+{
+ checkMemberTypes();
+ checkRecursion();
+}
+
+void StructDefinition::checkMemberTypes()
+{
+ for (ASTPointer<VariableDeclaration> const& member: getMembers())
+ if (!member->getType()->canBeStored())
+ BOOST_THROW_EXCEPTION(member->createTypeError("Type cannot be used in struct."));
+}
+
+void StructDefinition::checkRecursion()
+{
+ set<StructDefinition const*> definitionsSeen;
+ vector<StructDefinition const*> queue = {this};
+ while (!queue.empty())
+ {
+ StructDefinition const* def = queue.back();
+ queue.pop_back();
+ if (definitionsSeen.count(def))
+ BOOST_THROW_EXCEPTION(ParserError() << errinfo_sourceLocation(def->getLocation())
+ << errinfo_comment("Recursive struct definition."));
+ definitionsSeen.insert(def);
+ for (ASTPointer<VariableDeclaration> const& member: def->getMembers())
+ if (member->getType()->getCategory() == Type::Category::STRUCT)
+ {
+ UserDefinedTypeName const& typeName = dynamic_cast<UserDefinedTypeName&>(*member->getTypeName());
+ queue.push_back(&dynamic_cast<StructDefinition const&>(*typeName.getReferencedDeclaration()));
+ }
+ }
+}
+
void ParameterList::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this))
@@ -258,7 +292,7 @@ void Literal::accept(ASTVisitor& _visitor)
_visitor.endVisit(*this);
}
-TypeError ASTNode::createTypeError(string const& _description)
+TypeError ASTNode::createTypeError(string const& _description) const
{
return TypeError() << errinfo_sourceLocation(getLocation()) << errinfo_comment(_description);
}