Jelajahi Sumber

got semantic analysis working

Nicolas Winkler 6 tahun lalu
induk
melakukan
f0f701f6ec
12 mengubah file dengan 241 tambahan dan 121 penghapusan
  1. 4 3
      src/Ast.cpp
  2. 24 22
      src/Ast.h
  3. 64 35
      src/AstVisitor.cpp
  4. 22 17
      src/AstVisitor.h
  5. 24 9
      src/Semantic.cpp
  6. 37 23
      src/Semantic.h
  7. 26 1
      src/TypeVisitor.cpp
  8. 6 6
      src/TypeVisitor.h
  9. 1 1
      src/Util.h
  10. 6 0
      src/Visitor.h
  11. 23 0
      src/main.cpp
  12. 4 4
      src/parser.y

+ 4 - 3
src/Ast.cpp

@@ -13,9 +13,9 @@ AstObject::~AstObject(void)
 
 
 #define ACCEPT_DEFINITION(ClassName, Visitor) \
-std::unique_ptr<qlow::sem::SemanticObject> ClassName::accept(Visitor& v, const sem::SymbolTable<sem::Class>& c) \
+std::unique_ptr<qlow::sem::SemanticObject> ClassName::accept(Visitor& v, sem::Scope& scope) \
 { \
-    v.visit(*this, c); \
+    return v.visit(*this, scope); \
 }
 
 ACCEPT_DEFINITION(Class, StructureVisitor)
@@ -31,6 +31,7 @@ ACCEPT_DEFINITION(Expression, StructureVisitor)
 ACCEPT_DEFINITION(FeatureCall, StructureVisitor)
 ACCEPT_DEFINITION(AssignmentStatement, StructureVisitor)
 ACCEPT_DEFINITION(NewVariableStatement, StructureVisitor)
+ACCEPT_DEFINITION(IntConst, StructureVisitor)
 ACCEPT_DEFINITION(UnaryOperation, StructureVisitor)
 ACCEPT_DEFINITION(BinaryOperation, StructureVisitor)
 
@@ -41,7 +42,7 @@ Statement::~Statement(void)
 }
 
 
-qlow::ast::IntConst::IntConst(const std::string& val, const qlow::CodePosition& p) :
+qlow::ast::IntConst::IntConst(std::string&& val, const qlow::CodePosition& p) :
     AstObject{ p },
     Expression{ p },
     value{ strtoull(val.c_str(), nullptr, 0) }

+ 24 - 22
src/Ast.h

@@ -30,7 +30,6 @@
 
 #include "Visitor.h"
 #include "Util.h"
-#include "Util.h"
 
 namespace qlow
 {
@@ -72,8 +71,10 @@ namespace qlow
         struct SemanticObject;
         struct Class;
         
-        template<typename T>
-        using SymbolTable = std::map<std::string, std::unique_ptr<T>>;
+        class Scope;
+
+//        template<typename T>
+//        using SymbolTable = std::map<std::string, std::unique_ptr<T>>;
     }
 }
 
@@ -92,7 +93,7 @@ struct qlow::CodePosition
 
 
 struct qlow::ast::AstObject :
-    public Visitable<std::unique_ptr<sem::SemanticObject>, const sem::SymbolTable<sem::Class>, StructureVisitor>
+    public Visitable<std::unique_ptr<sem::SemanticObject>, sem::Scope&, StructureVisitor>
 {
     CodePosition pos;
     
@@ -114,7 +115,7 @@ struct qlow::ast::Class : public AstObject
     {
     }
 
-    std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, const sem::SymbolTable<sem::Class>&) override;
+    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&) override;
 };
 
 
@@ -129,7 +130,7 @@ struct qlow::ast::FeatureDeclaration : public AstObject
     {
     }
 
-    std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, const sem::SymbolTable<sem::Class>&);
+    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
 };
 
 
@@ -140,7 +141,7 @@ struct qlow::ast::FieldDeclaration : public FeatureDeclaration
     {
     }
 
-    std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, const sem::SymbolTable<sem::Class>&);
+    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
 };
 
 
@@ -165,7 +166,7 @@ struct qlow::ast::MethodDefinition : public FeatureDeclaration
     {
     }
 
-    std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, const sem::SymbolTable<sem::Class>&);
+    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
 };
 
 
@@ -179,7 +180,7 @@ struct qlow::ast::VariableDeclaration  : public AstObject
     {
     }
 
-    std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, const sem::SymbolTable<sem::Class>&);
+    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
 };
 
 
@@ -191,7 +192,7 @@ struct qlow::ast::ArgumentDeclaration :
     {
     }
 
-    std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, const sem::SymbolTable<sem::Class>&);
+    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
 };
 
 
@@ -205,7 +206,7 @@ struct qlow::ast::DoEndBlock : public AstObject
     {
     }
 
-    std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, const sem::SymbolTable<sem::Class>&);
+    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
 };
 
 
@@ -216,7 +217,7 @@ struct qlow::ast::Statement : public virtual AstObject
         
     virtual ~Statement(void);
 
-    std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, const sem::SymbolTable<sem::Class>&);
+    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
 };
 
 
@@ -225,7 +226,7 @@ struct qlow::ast::Expression : public virtual AstObject
     inline Expression(const CodePosition& cp) :
         AstObject{ cp } {}
         
-    std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, const sem::SymbolTable<sem::Class>&);
+    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
 };
 
 
@@ -251,7 +252,7 @@ struct qlow::ast::FeatureCall : public Expression, public Statement
     {
     }
 
-    std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, const sem::SymbolTable<sem::Class>&);
+    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
 };
 
 
@@ -260,14 +261,14 @@ struct qlow::ast::AssignmentStatement : public Statement
     std::unique_ptr<Expression> target;
     std::unique_ptr<Expression> expr;
 
-    inline AssignmentStatement(std::unique_ptr<Expression> target, std::unique_ptr<Expression> expr, const CodePosition& cp) :
+    inline AssignmentStatement(std::unique_ptr<Expression>&& target, std::unique_ptr<Expression>&& expr, const CodePosition& cp) :
         AstObject{ cp },
         Statement{ cp },
         target{ std::move(target) }, expr{ std::move(expr) }
     {
     }
 
-    std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, const sem::SymbolTable<sem::Class>&);
+    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
 };
 
 
@@ -275,14 +276,14 @@ struct qlow::ast::NewVariableStatement : public Statement
 {
     std::string name;
     std::string type;
-    inline NewVariableStatement(const std::string& name, const std::string& type, const CodePosition& cp) :
+    inline NewVariableStatement(std::string&& name, std::string&& type, const CodePosition& cp) :
         AstObject{ cp },
         Statement{ cp },
-       name(name), type(type)
+       name{ name }, type{ type }
     {
     } 
 
-    std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, const sem::SymbolTable<sem::Class>&);
+    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
 };
 
 
@@ -295,7 +296,8 @@ struct qlow::ast::IntConst : public Expression
         Expression(p),
         value{ v } {}
         
-    IntConst(const std::string& val, const CodePosition& p);
+    IntConst(std::string&& val, const CodePosition& p);
+    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
 };
 
 
@@ -334,7 +336,7 @@ struct qlow::ast::UnaryOperation : public Operation
     {
     }
 
-    std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, const sem::SymbolTable<sem::Class>&);
+    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
 };
 
 
@@ -350,7 +352,7 @@ struct qlow::ast::BinaryOperation : public Operation
     {
     }
 
-    std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, const sem::SymbolTable<sem::Class>&);
+    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
 };
 
 

+ 64 - 35
src/AstVisitor.cpp

@@ -1,21 +1,23 @@
 #include "AstVisitor.h"
 #include "Ast.h"
 
+#include <typeinfo>
+
 #include "Util.h"
 
 using namespace qlow;
 
 
-sem::Class* StructureVisitor::getType(const std::string& type, const sem::SymbolTable<sem::Class>& classes)
+sem::Class* StructureVisitor::getType(const std::string& type, sem::Scope& scope)
 {
-    auto t = classes.find(type);
-    if (t != classes.end())
-        return t->second.get();
+    auto t = scope.getType(type);
+    if (t)
+        return t.value().typeClass;
     else
         return nullptr;
 }
 
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::Class& ast, const sem::SymbolTable<sem::Class>& classes)
+std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::Class& ast, sem::Scope& scope)
 {
     auto c = std::make_unique<sem::Class>();
     c->name = ast.name;
@@ -23,18 +25,22 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::Class& ast, co
 }
 
 
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureDeclaration& ast, const sem::SymbolTable<sem::Class>& classes)
+std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureDeclaration& ast, sem::Scope& scope)
 {
     // not needed, because 
+    throw "shouldn't be called";
 }
 
 
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FieldDeclaration& ast, const sem::SymbolTable<sem::Class>& classes)
+std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FieldDeclaration& ast, sem::Scope& scope)
 {
     auto f = std::make_unique<sem::Field>();
     f->name = ast.name;
-    f->type = getType(ast.type, classes);
-    if (f->type == nullptr) {
+    auto type = scope.getType(ast.type);
+    if (type) {
+        f->type = type.value().typeClass;
+    }
+    else {
         throw sem::SemanticException(sem::SemanticException::UNKNOWN_TYPE,
             ast.type,
             ast.pos
@@ -44,28 +50,34 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FieldDeclarati
 }
 
 
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::MethodDefinition& ast, const sem::SymbolTable<sem::Class>& classes)
+std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::MethodDefinition& ast, sem::Scope& scope)
 {
     auto m = std::make_unique<sem::Method>();
     m->name = ast.name;
-    m->returnType = getType(ast.type, classes);
-    m->astNode = &ast;
-    if (m->returnType == nullptr) {
+    auto returnType = scope.getType(ast.type);
+    if (returnType) {
+        m->returnType = returnType.value();
+    }
+    else {
         throw sem::SemanticException(sem::SemanticException::UNKNOWN_TYPE,
             ast.type,
             ast.pos
         );
     }
+    m->astNode = &ast;
     return m;
 }
 
 
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::VariableDeclaration& ast, const sem::SymbolTable<sem::Class>& classes)
+std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::VariableDeclaration& ast, sem::Scope& scope)
 {
     auto v = std::make_unique<sem::Variable>();
     v->name = ast.name;
-    v->type = getType(ast.type, classes);
-    if (v->type == nullptr) {
+    auto type = scope.getType(ast.type);
+    if (type) {
+        v->type = type.value().typeClass;
+    }
+    else {
         throw sem::SemanticException(sem::SemanticException::UNKNOWN_TYPE,
             ast.type,
             ast.pos
@@ -75,26 +87,29 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::VariableDeclar
 }
 
 
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::ArgumentDeclaration& ast, const sem::SymbolTable<sem::Class>& classes)
+std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::ArgumentDeclaration& ast, sem::Scope& scope)
 {
+    throw "shouldn't be called";
 }
 
 
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::DoEndBlock& ast, const sem::SymbolTable<sem::Class>& classes)
+std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::DoEndBlock& ast, sem::Scope& scope)
 {
     auto body = std::make_unique<sem::DoEndBlock>();
     for (auto& statement : ast.statements) {
         
         if (ast::NewVariableStatement* nvs = dynamic_cast<ast::NewVariableStatement*>(statement.get()); nvs) {
-            auto var = std::make_unique<sem::Variable>(getType(nvs->type, classes), nvs->name);
-            if (var->type == nullptr)
+            auto type = scope.getType(nvs->type);
+
+            if (!type)
                 throw sem::SemanticException(sem::SemanticException::UNKNOWN_TYPE, nvs->type, nvs->pos);
-            
+
+            auto var = std::make_unique<sem::Variable>(type.value().typeClass, nvs->name);
             body->variables.push_back(std::move(var));
             continue;
         }
         
-        auto v = visit(*statement, classes);
+        auto v = statement->accept(*this, scope);
         if (dynamic_cast<sem::FeatureCallExpression*>(v.get()) != nullptr) {
             body->statements.push_back(std::make_unique<sem::FeatureCallStatement>(unique_dynamic_cast<sem::FeatureCallExpression>(std::move(v))));
         }
@@ -106,55 +121,69 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::DoEndBlock& as
 }
 
 
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::Statement& ast, const sem::SymbolTable<sem::Class>& classes)
+std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::Statement& ast, sem::Scope& scope)
 {
+    printf("at: %d:%d to %d:%d\n", ast.pos.first_line, ast.pos.first_column, ast.pos.last_line, ast.pos.last_column);
+    printf("type: %s\n", typeid(ast).name());
+    throw "visit(Statement) shouldn't be called";
 }
 
 
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::Expression& ast, const sem::SymbolTable<sem::Class>& classes)
+std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::Expression& ast, sem::Scope& scope)
 {
+    throw "visit(Expression) shouldn't be called";
 }
 
 
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureCall& ast, const sem::SymbolTable<sem::Class>& classes)
+std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureCall& ast, sem::Scope& scope)
 {
     auto fce = std::make_unique<sem::FeatureCallExpression>();
-    //fce->callee = unique_dynamic_cast<sem::Expression>(visit(*ast.target, classes));
+    //fce->target = unique_dynamic_cast<sem::Expression>(ast.target.accept(*this, classes));
+    fce->callee = scope.getMethod(ast.name);
     return fce;
 }
 
 
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::AssignmentStatement& ast, const sem::SymbolTable<sem::Class>& classes)
+std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::AssignmentStatement& ast, sem::Scope& scope)
 {
     auto as = std::make_unique<sem::AssignmentStatement>();
     
-    as->value = unique_dynamic_cast<sem::Expression>(visit(*ast.expr, classes));
-    as->target = unique_dynamic_cast<sem::Expression>(visit(*ast.target, classes));
+//    as->value = unique_dynamic_cast<sem::Expression>(visit(*ast.expr, classes));
+//    as->target = unique_dynamic_cast<sem::Expression>(visit(*ast.target, classes));
+    as->value = unique_dynamic_cast<sem::Expression>(ast.expr->accept(*this, scope));
+    as->target = unique_dynamic_cast<sem::Expression>(ast.target->accept(*this, scope));
     return as;
 }
 
 
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::NewVariableStatement& ast, const sem::SymbolTable<sem::Class>& classes)
+std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::NewVariableStatement& ast, sem::Scope& scope)
+{
+    throw "shouldn't be called";
+}
+
+
+std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::IntConst& ast, sem::Scope& scope)
 {
+    return std::make_unique<sem::IntConst>(ast.value);
 }
 
 
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::UnaryOperation& ast, const sem::SymbolTable<sem::Class>& classes)
+std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::UnaryOperation& ast, sem::Scope& scope)
 {
     auto ret = std::make_unique<sem::UnaryOperation>();
     ret->op = ast.op;
     ret->side = ast.side;
-    ret->arg = unique_dynamic_cast<sem::Expression>(visit(*ast.expr, classes));
+    ret->arg = unique_dynamic_cast<sem::Expression>(ast.expr->accept(*this, scope));
     return ret;
 }
 
 
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::BinaryOperation& ast, const sem::SymbolTable<sem::Class>& classes)
+std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::BinaryOperation& ast, sem::Scope& scope)
 {
     auto ret = std::make_unique<sem::BinaryOperation>();
     ret->op = ast.op;
-    ret->left = unique_dynamic_cast<sem::Expression>(visit(*ast.left, classes));
-    ret->right = unique_dynamic_cast<sem::Expression>(visit(*ast.right, classes));
+    ret->left = unique_dynamic_cast<sem::Expression>(ast.left->accept(*this, scope));
+    ret->right = unique_dynamic_cast<sem::Expression>(ast.right->accept(*this, scope));
     return ret;
 }
 

+ 22 - 17
src/AstVisitor.h

@@ -4,6 +4,8 @@
 #include "Visitor.h"
 #include "Ast.h"
 #include "Semantic.h"
+#include "Scope.h"
+
 
 #include <memory>
 
@@ -36,6 +38,7 @@ namespace qlow
         struct FeatureCall;
         struct AssignmentStatement;
         struct NewVariableStatement;
+        struct IntConst;
 
         struct Operation;
         struct UnaryOperation;
@@ -53,7 +56,7 @@ namespace qlow
 class qlow::StructureVisitor :
     public Visitor<
         std::unique_ptr<sem::SemanticObject>,
-        const sem::SymbolTable<sem::Class>&,
+        sem::Scope&,
 
         ast::Class,
         ast::FeatureDeclaration,
@@ -67,6 +70,7 @@ class qlow::StructureVisitor :
         ast::FeatureCall,
         ast::AssignmentStatement,
         ast::NewVariableStatement,
+        ast::IntConst,
         ast::UnaryOperation,
         ast::BinaryOperation
     >
@@ -78,22 +82,23 @@ public:
      * 
      * \returns <code>nullptr</code> if type is not found.
      */
-    sem::Class* getType(const std::string& type, const sem::SymbolTable<sem::Class>& classes);
-
-    ReturnType visit(ast::Class& ast, const sem::SymbolTable<sem::Class>& classes) override;
-    ReturnType visit(ast::FeatureDeclaration& ast, const sem::SymbolTable<sem::Class>& classes) override;
-    ReturnType visit(ast::FieldDeclaration& ast, const sem::SymbolTable<sem::Class>& classes) override;
-    ReturnType visit(ast::MethodDefinition& ast, const sem::SymbolTable<sem::Class>& classes) override;
-    ReturnType visit(ast::VariableDeclaration& ast, const sem::SymbolTable<sem::Class>& classes) override;
-    ReturnType visit(ast::ArgumentDeclaration& ast, const sem::SymbolTable<sem::Class>& classes) override;
-    ReturnType visit(ast::DoEndBlock& ast, const sem::SymbolTable<sem::Class>& classes) override;
-    ReturnType visit(ast::Statement& ast, const sem::SymbolTable<sem::Class>& classes) override;
-    ReturnType visit(ast::Expression& ast, const sem::SymbolTable<sem::Class>& classes) override;
-    ReturnType visit(ast::FeatureCall& ast, const sem::SymbolTable<sem::Class>& classes) override;
-    ReturnType visit(ast::AssignmentStatement& ast, const sem::SymbolTable<sem::Class>& classes) override;
-    ReturnType visit(ast::NewVariableStatement& ast, const sem::SymbolTable<sem::Class>& classes) override;
-    ReturnType visit(ast::UnaryOperation& ast, const sem::SymbolTable<sem::Class>& classes) override;
-    ReturnType visit(ast::BinaryOperation& ast, const sem::SymbolTable<sem::Class>& classes) override;
+    sem::Class* getType(const std::string& type, sem::Scope& scope);
+
+    ReturnType visit(ast::Class& ast, sem::Scope& scope) override;
+    ReturnType visit(ast::FeatureDeclaration& ast, sem::Scope& scope) override;
+    ReturnType visit(ast::FieldDeclaration& ast, sem::Scope& scope) override;
+    ReturnType visit(ast::MethodDefinition& ast, sem::Scope& scope) override;
+    ReturnType visit(ast::VariableDeclaration& ast, sem::Scope& scope) override;
+    ReturnType visit(ast::ArgumentDeclaration& ast, sem::Scope& scope) override;
+    ReturnType visit(ast::DoEndBlock& ast, sem::Scope& scope) override;
+    ReturnType visit(ast::Statement& ast, sem::Scope& scope) override;
+    ReturnType visit(ast::Expression& ast, sem::Scope& scope) override;
+    ReturnType visit(ast::FeatureCall& ast, sem::Scope& scope) override;
+    ReturnType visit(ast::AssignmentStatement& ast, sem::Scope& scope) override;
+    ReturnType visit(ast::NewVariableStatement& ast, sem::Scope& scope) override;
+    ReturnType visit(ast::IntConst& ast, sem::Scope& scope) override;
+    ReturnType visit(ast::UnaryOperation& ast, sem::Scope& scope) override;
+    ReturnType visit(ast::BinaryOperation& ast, sem::Scope& scope) override;
 };
 
 

+ 24 - 9
src/Semantic.cpp

@@ -11,19 +11,27 @@ namespace sem
 {
 
 SymbolTable<qlow::sem::Class>
-    createFromAst(std::vector<std::unique_ptr<qlow::ast::Class>>& classes)
+    createFromAst(const std::vector<std::unique_ptr<qlow::ast::Class>>& classes)
 {
 
+#ifdef DEBUGGING
+    printf("starting building semantic representation\n");
+#endif
+
     // create classes
-    SymbolTable<sem::Class> semClasses;
+    sem::GlobalScope globalScope;
     for (auto& astClass : classes) {
-        semClasses[astClass->name] = std::make_unique<sem::Class>(astClass.get());
+        globalScope.classes[astClass->name] = std::make_unique<sem::Class>(astClass.get());
     }
 
+#ifdef DEBUGGING
+    printf("created symbol table entries for all classes\n");
+#endif 
+        
     StructureVisitor av;
     
     // create all methods and fields
-    for (auto& [name, semClass] : semClasses) {
+    for (auto& [name, semClass] : globalScope.classes) {
         for (auto& feature : semClass->astNode->features) {
             
             if (auto* field = dynamic_cast<qlow::ast::FieldDeclaration*> (feature.get()); field) {
@@ -31,14 +39,14 @@ SymbolTable<qlow::sem::Class>
                     throw SemanticException(SemanticException::DUPLICATE_FIELD_DECLARATION, field->name, field->pos);
                 
                 // otherwise add to the fields list
-                semClass->fields[field->name] = unique_dynamic_cast<Field>(av.visit(*field, semClasses));
+                semClass->fields[field->name] = unique_dynamic_cast<Field>(field->accept(av, globalScope));
             }
             else if (auto* method = dynamic_cast<qlow::ast::MethodDefinition*> (feature.get()); method) {
                 if (semClass->methods.find(method->name) != semClass->methods.end()) // throw, if method already exists
                     throw SemanticException(SemanticException::DUPLICATE_METHOD_DEFINITION, method->name, method->pos);
                 
                 // otherwise add to the methods list
-                semClass->methods[method->name] = unique_dynamic_cast<Method>(av.visit(*method, semClasses));
+                semClass->methods[method->name] = unique_dynamic_cast<Method>(method->accept(av, globalScope));
             }
             else {
                 // if a feature is neither a method nor a field, something went horribly wrong
@@ -47,13 +55,20 @@ SymbolTable<qlow::sem::Class>
         }
     }
     
-    for (auto& [name, semClass] : semClasses) {
+#ifdef DEBUGGING
+    printf("created all methods and fields\n");
+#endif
+    
+    for (auto& [name, semClass] : globalScope.classes) {
         for (auto& [name, method] : semClass->methods) {
-            method->body = unique_dynamic_cast<sem::DoEndBlock>(av.visit(*method->astNode->body, semClasses));
+            method->body = unique_dynamic_cast<sem::DoEndBlock>(av.visit(*method->astNode->body, globalScope));
         }
     }
+#ifdef DEBUGGING
+    printf("created all method bodies\n");
+#endif
     
-    return semClasses;
+    return std::move(globalScope.classes);
 }
 
 }

+ 37 - 23
src/Semantic.h

@@ -10,23 +10,23 @@ namespace qlow
 {
     namespace sem
     {
-        
-        SymbolTable<qlow::sem::Class> createFromAst(std::vector<std::unique_ptr<qlow::ast::Class>>& classes);
-        
         /*!
          * \note contains owning pointers to elements
          */
         template<typename T>
         using SymbolTable = std::map<std::string, std::unique_ptr<T>>;
 
+        
+        SymbolTable<qlow::sem::Class> createFromAst(const std::vector<std::unique_ptr<qlow::ast::Class>>& classes);
+
         struct SemanticObject;
         struct Class;
 
+        struct Variable;
+
         struct Field;
         struct Method;
 
-        struct Variable;
-
         struct DoEndBlock;
         struct Statement;
         struct Expression;
@@ -40,6 +40,8 @@ namespace qlow
 
         struct FeatureCallExpression;
         
+        struct IntConst;
+        
         struct Type;
 
         class SemanticException;
@@ -47,6 +49,12 @@ namespace qlow
 }
 
 
+struct qlow::sem::Type
+{
+    Class* typeClass;
+};
+
+
 struct qlow::sem::SemanticObject
 {
     virtual ~SemanticObject(void);
@@ -64,7 +72,7 @@ struct qlow::sem::Class : public SemanticObject
     std::string name;
     SymbolTable<Field> fields;
     SymbolTable<Method> methods;
-
+    
     Class(void) = default;
     inline Class(qlow::ast::Class* astNode) :
         astNode{ astNode }, name{ astNode->name }
@@ -75,34 +83,35 @@ struct qlow::sem::Class : public SemanticObject
 };
 
 
-struct qlow::sem::Field : public SemanticObject
+struct qlow::sem::Variable : public SemanticObject
 {
     Class* type;
     std::string name;
     
-    virtual std::string toString(void) const override;
+    Variable(void) = default;
+    inline Variable(Class* type, std::string& name) :
+        type{ type }, name{ name } {}
 };
 
 
-struct qlow::sem::Method : public SemanticObject
+struct qlow::sem::Field : public Variable
 {
-    Class* returnType;
+    Class* type;
     std::string name;
-    ast::MethodDefinition* astNode;
-    std::unique_ptr<DoEndBlock> body;
     
     virtual std::string toString(void) const override;
 };
 
 
-struct qlow::sem::Variable : public SemanticObject
+struct qlow::sem::Method : public SemanticObject
 {
-    Class* type;
+    Class* containingType;
+    Type returnType;
     std::string name;
+    ast::MethodDefinition* astNode;
+    std::unique_ptr<DoEndBlock> body;
     
-    Variable(void) = default;
-    inline Variable(Class* type, std::string& name) :
-        type{ type }, name{ name } {}
+    virtual std::string toString(void) const override;
 };
 
 
@@ -156,17 +165,22 @@ struct qlow::sem::FeatureCallExpression : public Expression
 };
 
 
-struct qlow::sem::FeatureCallStatement : public Statement 
+struct qlow::sem::IntConst : public Expression
 {
-    std::unique_ptr<FeatureCallExpression> expr;
-    inline FeatureCallStatement(std::unique_ptr<FeatureCallExpression> expr) :
-        expr{ std::move(expr) } {}
+    unsigned long long value;
+
+    inline IntConst(unsigned long long value) :
+        value{ value }
+    {
+    }
 };
 
 
-struct qlow::sem::Type
+struct qlow::sem::FeatureCallStatement : public Statement 
 {
-    Class* typeClass;
+    std::unique_ptr<FeatureCallExpression> expr;
+    inline FeatureCallStatement(std::unique_ptr<FeatureCallExpression> expr) :
+        expr{ std::move(expr) } {}
 };
 
 

+ 26 - 1
src/TypeVisitor.cpp

@@ -6,8 +6,33 @@ using namespace qlow;
 
 sem::Type sem::TypeVisitor::visit(sem::Expression& expr, const sem::SymbolTable<sem::Class>& classes)
 {
-    
 }
 
 
+sem::Type sem::TypeVisitor::visit(sem::UnaryOperation& expr, const sem::SymbolTable<sem::Class>& classes)
+{
+    return visit(*expr.arg, classes);
+}
+
+
+sem::Type sem::TypeVisitor::visit(sem::BinaryOperation& expr, const sem::SymbolTable<sem::Class>& classes)
+{
+    return visit(*expr.left, classes);
+}
+
+
+sem::Type sem::TypeVisitor::visit(sem::FeatureCallExpression& expr, const sem::SymbolTable<sem::Class>& classes)
+{
+    return Type{ expr.callee->returnType };
+}
+
+
+sem::Type sem::TypeVisitor::visit(sem::IntConst& expr, const sem::SymbolTable<sem::Class>& classes)
+{
+    return Type{ new sem::Class() };
+}
+
+
+
+
 

+ 6 - 6
src/TypeVisitor.h

@@ -19,19 +19,19 @@ class qlow::sem::TypeVisitor :
         const sem::SymbolTable<sem::Class>,
         
         sem::Expression,
-        sem::Variable,
         sem::UnaryOperation,
         sem::BinaryOperation,
-        sem::FeatureCallExpression
+        sem::FeatureCallExpression,
+        sem::IntConst
     >
 {
     
 public:
     qlow::sem::Type visit(sem::Expression& expr, const sem::SymbolTable<sem::Class>& classes) override;
-    qlow::sem::Type visit(sem::Expression& expr, const sem::SymbolTable<sem::Class>& classes) override;
-    qlow::sem::Type visit(sem::Expression& expr, const sem::SymbolTable<sem::Class>& classes) override;
-    qlow::sem::Type visit(sem::Expression& expr, const sem::SymbolTable<sem::Class>& classes) override;
-    qlow::sem::Type visit(sem::Expression& expr, const sem::SymbolTable<sem::Class>& classes) override;
+    qlow::sem::Type visit(sem::UnaryOperation& expr, const sem::SymbolTable<sem::Class>& classes) override;
+    qlow::sem::Type visit(sem::BinaryOperation& expr, const sem::SymbolTable<sem::Class>& classes) override;
+    qlow::sem::Type visit(sem::FeatureCallExpression& expr, const sem::SymbolTable<sem::Class>& classes) override;
+    qlow::sem::Type visit(sem::IntConst& expr, const sem::SymbolTable<sem::Class>& classes) override;
 };
 
 #endif // QLOW_SEM_TYPEVISITOR_H

+ 1 - 1
src/Util.h

@@ -14,7 +14,7 @@ namespace qlow
     
     
     
-    /// i don't like this, but I lack better ideas at the moment.
+    /// I don't like this, but I lack better ideas at the moment.
     /// TODO: find better solution
     /*!
     * \brief tries to cast a unique_ptr and throws if it fails

+ 6 - 0
src/Visitor.h

@@ -21,6 +21,9 @@ namespace qlow
     public:
         using ReturnType = R;
         virtual R visit(T& arg, A& arg2) = 0;
+        inline R invokeVisit(T& arg, A& arg2) {
+            arg.accept(*this, arg2);
+        }
     };
 
 
@@ -32,6 +35,9 @@ namespace qlow
         using Visitor<R, A, V...>::visit;
         using ReturnType = R;
         virtual R visit(T& arg, A& arg2) = 0;
+        inline R invokeVisit(T& arg, A& arg2) {
+            arg.accept(*this, arg2);
+        }
     };
 
 

+ 23 - 0
src/main.cpp

@@ -23,6 +23,7 @@ int main(int argc, char** argv)
         }
     }
     
+    {
     const char* filename = argv[optind];
     
     try {
@@ -42,6 +43,23 @@ int main(int argc, char** argv)
         for (auto& [a, b] : semClasses) {
             std::cout << a << ": " << b->toString() << std::endl;
         }
+
+        auto main = semClasses.find("Main");
+        qlow::sem::Class* mainClass = nullptr;
+        if (main == semClasses.end()) {
+            throw "No Main class found!";
+        }
+        else {
+            mainClass = main->second.get();
+        }
+        auto mainmain = mainClass->methods.find("main");
+        qlow::sem::Method* mainMethod = nullptr;
+        if (mainmain == mainClass->methods.end()) {
+            throw "No main method found inside Main class!";
+        }
+        else {
+            mainMethod = mainmain->second.get();
+        }
     }
     catch (qlow::sem::SemanticException& se)
     {
@@ -57,6 +75,11 @@ int main(int argc, char** argv)
     
     if (::qlow_parser_in != stdin)
         fclose(::qlow_parser_in);
+    }
+
+    for (auto&& c : *parsedClasses) {
+        delete c.release();
+    }
 }
 
 

+ 4 - 4
src/parser.y

@@ -209,7 +209,7 @@ argumentDeclaration:
 doEndBlock:
     DO statements END {
         $$ = new DoEndBlock(std::move(*$2), @$);
-        delete $2; $2 = 0;
+        delete $2; $2 = nullptr;
     };
 
 
@@ -304,7 +304,8 @@ expression:
     }
     |
     INT_LITERAL {
-        $$ = new IntConst($1);
+        $$ = new IntConst(std::move(*$1), @$);
+        delete $1;
     };
 
 
@@ -356,13 +357,12 @@ paranthesesExpression:
 assignmentStatement:
     expression ASSIGN expression {
         $$ = new AssignmentStatement(std::unique_ptr<Expression>($1), std::unique_ptr<Expression>($3), @$);
-        delete $1; $1 = 0;
     };
 
 
 newVariableStatement:
     IDENTIFIER COLON IDENTIFIER {
-        $$ = new NewVariableStatement(*$3, *$1, @$);
+        $$ = new NewVariableStatement(std::move(*$1), std::move(*$3), @$);
         delete $3; delete $1; $3 = 0; $1 = 0;
     };