Semantic.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #include "Semantic.h"
  2. #include "Ast.h"
  3. #include "AstVisitor.h"
  4. #include "CodegenVisitor.h"
  5. #include "Util.h"
  6. using namespace qlow::sem;
  7. namespace qlow
  8. {
  9. namespace sem
  10. {
  11. std::unique_ptr<GlobalScope>
  12. createFromAst(const std::vector<std::unique_ptr<qlow::ast::AstObject>>& objects)
  13. {
  14. Logger& logger = Logger::getInstance();
  15. #ifdef DEBUGGING
  16. printf("starting building semantic representation\n");
  17. #endif
  18. // create classes
  19. std::unique_ptr<sem::GlobalScope> globalScope = std::make_unique<sem::GlobalScope>();
  20. for (auto& astObject : objects) {
  21. if (auto* cls = dynamic_cast<ast::Class*>(astObject.get()); cls) {
  22. globalScope->classes[cls->name] = std::make_unique<sem::Class>(cls, *globalScope);
  23. }
  24. else if (auto* function = dynamic_cast<ast::MethodDefinition*>(astObject.get()); function) {
  25. globalScope->functions[function->name] = std::make_unique<sem::Method>(function, *globalScope);
  26. }
  27. }
  28. #ifdef DEBUGGING
  29. printf("created symbol table entries for all classes\n");
  30. #endif
  31. StructureVisitor av;
  32. // create all methods and fields
  33. for (auto& [name, semClass] : globalScope->classes) {
  34. for (auto& feature : semClass->astNode->features) {
  35. if (auto* field = dynamic_cast<qlow::ast::FieldDeclaration*> (feature.get()); field) {
  36. if (semClass->fields.find(field->name) != semClass->fields.end()) // throw, if field already exists
  37. throw SemanticError(SemanticError::DUPLICATE_FIELD_DECLARATION, field->name, field->pos);
  38. // otherwise add to the fields list
  39. semClass->fields[field->name] = unique_dynamic_cast<Field>(field->accept(av, semClass->scope));
  40. }
  41. else if (auto* method = dynamic_cast<qlow::ast::MethodDefinition*> (feature.get()); method) {
  42. if (semClass->methods.find(method->name) != semClass->methods.end()) // throw, if method already exists
  43. throw SemanticError(SemanticError::DUPLICATE_METHOD_DEFINITION, method->name, method->pos);
  44. // otherwise add to the methods list
  45. semClass->methods[method->name] = unique_dynamic_cast<Method>(method->accept(av, semClass->scope));
  46. }
  47. else {
  48. // if a feature is neither a method nor a field, something went horribly wrong
  49. throw "internal error";
  50. }
  51. }
  52. }
  53. for (auto& [name, method] : globalScope->functions) {
  54. auto returnType = globalScope->getType(method->astNode->type);
  55. if (returnType) {
  56. method->returnType = returnType.value();
  57. }
  58. else {
  59. SemanticError se(SemanticError::UNKNOWN_TYPE, method->astNode->type, method->astNode->pos);
  60. }
  61. }
  62. #ifdef DEBUGGING
  63. printf("created all methods and fields\n");
  64. #endif
  65. for (auto& [name, semClass] : globalScope->classes) {
  66. for (auto& [name, method] : semClass->methods) {
  67. method->body = unique_dynamic_cast<sem::DoEndBlock>(av.visit(*method->astNode->body, method->scope));
  68. }
  69. }
  70. #ifdef DEBUGGING
  71. printf("created all method bodies\n");
  72. #endif
  73. return globalScope;
  74. }
  75. }
  76. }
  77. SemanticObject::~SemanticObject(void)
  78. {
  79. }
  80. std::string SemanticObject::toString(void) const
  81. {
  82. return "SemanticObject [" + util::toString(this) + "]";
  83. }
  84. std::string Class::toString(void) const
  85. {
  86. std::string val = "Class[";
  87. // add fields
  88. for (auto& field : fields)
  89. val += field.second->toString() + ", ";
  90. if (!fields.empty())
  91. val = val.substr(0, val.length() - 2);
  92. // add methods
  93. for (auto& method : methods)
  94. val += method.second->toString() + ", ";
  95. if (!methods.empty())
  96. val = val.substr(0, val.length() - 2);
  97. val += " (";
  98. val += std::to_string(this->astNode->pos.first_line) + ", ";
  99. val += std::to_string(this->astNode->pos.first_column);
  100. val += " )";
  101. return val + "]";
  102. }
  103. std::string Variable::toString(void) const
  104. {
  105. return "Variable[" + this->name + "]";
  106. }
  107. std::string Field::toString(void) const
  108. {
  109. return "Field[" + this->name + "]";
  110. }
  111. std::string Method::toString(void) const
  112. {
  113. return "Method[" + this->name + "]";
  114. }
  115. #define COMMA ,
  116. #define ACCEPT_DEFINITION(ClassName, Visitor, ReturnType, Arg) \
  117. ReturnType ClassName::accept(Visitor& v, Arg arg) \
  118. { \
  119. return v.visit(*this, arg); \
  120. }
  121. ACCEPT_DEFINITION(LocalVariableExpression, ExpressionVisitor, std::pair<llvm::Value* COMMA Type>, llvm::IRBuilder<>&)
  122. ACCEPT_DEFINITION(BinaryOperation, ExpressionVisitor, std::pair<llvm::Value* COMMA Type>, llvm::IRBuilder<>&)
  123. ACCEPT_DEFINITION(UnaryOperation, ExpressionVisitor, std::pair<llvm::Value* COMMA Type>, llvm::IRBuilder<>&)
  124. ACCEPT_DEFINITION(FeatureCallExpression, ExpressionVisitor, std::pair<llvm::Value* COMMA Type>, llvm::IRBuilder<>&)
  125. ACCEPT_DEFINITION(IntConst, ExpressionVisitor, std::pair<llvm::Value* COMMA Type>, llvm::IRBuilder<>&)
  126. ACCEPT_DEFINITION(AssignmentStatement, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&)
  127. ACCEPT_DEFINITION(DoEndBlock, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&)
  128. ACCEPT_DEFINITION(IfElseBlock, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&)
  129. ACCEPT_DEFINITION(ReturnStatement, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&)
  130. ACCEPT_DEFINITION(FeatureCallStatement, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&)
  131. std::string AssignmentStatement::toString(void) const
  132. {
  133. return "AssignmentStatement[" + this->target->toString() + " := " +
  134. this->value->toString() + "]";
  135. }
  136. std::string ReturnStatement::toString(void) const
  137. {
  138. return "ReturnStatement[" + this->value->toString() + "]";
  139. }
  140. std::string LocalVariableExpression::toString(void) const
  141. {
  142. return "LocalVariableExpression[" + var->name + "]";
  143. }
  144. std::string BinaryOperation::toString(void) const
  145. {
  146. return "BinaryOperation[" + left->toString() + ", " +
  147. right->toString() + "]";
  148. }
  149. std::string UnaryOperation::toString(void) const
  150. {
  151. return "UnaryOperation[" + arg->toString() + "]";
  152. }
  153. std::string FeatureCallExpression::toString(void) const
  154. {
  155. return "FeatureCallExpression[" + callee->toString() + "]";
  156. }
  157. std::string FeatureCallStatement::toString(void) const
  158. {
  159. return "FeatureCallStatement[" + expr->callee->toString() + "]";
  160. }