Nicolas Winkler 6 лет назад
Родитель
Сommit
c05c162e71
9 измененных файлов с 111 добавлено и 85 удалено
  1. 6 27
      src/AstVisitor.cpp
  2. 0 6
      src/AstVisitor.h
  3. 23 5
      src/Scope.cpp
  4. 21 4
      src/Scope.h
  5. 6 6
      src/Semantic.h
  6. 16 5
      src/Type.cpp
  7. 26 19
      src/Type.h
  8. 7 7
      src/TypeVisitor.cpp
  9. 6 6
      src/TypeVisitor.h

+ 6 - 27
src/AstVisitor.cpp

@@ -8,20 +8,6 @@
 using namespace qlow;
 
 
-[[deprecated]]
-sem::Class* StructureVisitor::getType(const std::string& type, sem::Scope& scope)
-{
-    auto t = scope.getType(type);
-    if (t) {
-        if (auto* ct = dynamic_cast<sem::ClassType*>(t.value()); ct)
-            return ct->getClass();
-        else
-            return nullptr;
-    }
-    else
-        return nullptr;
-}
-
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::Class& ast, sem::Scope& scope)
 {
     //auto c = std::make_unique<sem::Class>();
@@ -44,11 +30,7 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FieldDeclarati
     f->name = ast.name;
     auto type = scope.getType(ast.type);
     if (type) {
-        if (auto* ct = dynamic_cast<sem::ClassType*>(type.value()); ct) {
-            f->type = ct->getClass();
-        }
-        else
-            throw "TODO implement";
+        f->type = type.value();
     }
     else {
         throw sem::SemanticException(sem::SemanticException::UNKNOWN_TYPE,
@@ -62,18 +44,15 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FieldDeclarati
 
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::MethodDefinition& ast, sem::Scope& scope)
 {
-    auto m = std::make_unique<sem::Method>(scope);
-    m->name = ast.name;
     auto returnType = scope.getType(ast.type);
-    if (returnType) {
-        m->returnType = returnType.value();
-    }
-    else {
+    if (!returnType) {
         throw sem::SemanticException(sem::SemanticException::UNKNOWN_TYPE,
             ast.type,
             ast.pos
         );
     }
+    auto m = std::make_unique<sem::Method>(scope, returnType.value());
+    m->name = ast.name;
     m->astNode = &ast;
     return m;
     //throw "  std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::MethodDefinition& ast, sem::Scope& scope) shouldn't be called";
@@ -86,7 +65,7 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::VariableDeclar
     v->name = ast.name;
     auto type = scope.getType(ast.type);
     if (type) {
-        v->type = type.value().typeClass;
+        v->type = type.value();
     }
     else {
         throw sem::SemanticException(sem::SemanticException::UNKNOWN_TYPE,
@@ -115,7 +94,7 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::DoEndBlock& as
             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);
+            auto var = std::make_unique<sem::Variable>(type.value(), nvs->name);
             body->scope.putVariable(nvs->name, std::move(var));
             continue;
         }

+ 0 - 6
src/AstVisitor.h

@@ -77,12 +77,6 @@ class qlow::StructureVisitor :
 {
 public:
     using ReturnType = std::unique_ptr<sem::SemanticObject>;
-    
-    /*!
-     * 
-     * \returns <code>nullptr</code> if type is not found.
-     */
-    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;

+ 23 - 5
src/Scope.cpp

@@ -20,11 +20,17 @@ sem::Method* sem::GlobalScope::getMethod(const std::string& name)
 }
 
 
-std::optional<sem::Type*> sem::GlobalScope::getType(const std::string& name)
+std::optional<sem::Type> sem::GlobalScope::getType(const std::string& name)
 {
     auto t = classes.find(name);
     if (t != classes.end())
-        return std::make_optional(new ClassType{ t->second.get() });
+        return std::make_optional(Type(t->second.get()));
+    return std::nullopt;
+}
+
+
+std::optional<sem::Type> sem::GlobalScope::getReturnableType(void)
+{
     return std::nullopt;
 }
 
@@ -81,12 +87,18 @@ std::string sem::ClassScope::toString(void)
 }
 
 
-std::optional<sem::Type*> sem::ClassScope::getType(const std::string& name)
+std::optional<sem::Type> sem::ClassScope::getType(const std::string& name)
 {
     return parentScope.getType(name);
 }
 
 
+std::optional<sem::Type> sem::ClassScope::getReturnableType(void)
+{
+    return std::nullopt;
+}
+
+
 void sem::LocalScope::putVariable(const std::string& name, std::unique_ptr<Variable> v)
 {
     localVariables.insert({name, std::move(v)});
@@ -109,18 +121,24 @@ sem::Variable* sem::LocalScope::getVariable(const std::string& name)
 }
 
 
-sem::Method * sem::LocalScope::getMethod(const std::string& name)
+sem::Method* sem::LocalScope::getMethod(const std::string& name)
 {
     return parentScope.getMethod(name);
 }
 
 
-std::optional<sem::Type*> sem::LocalScope::getType(const std::string& name)
+std::optional<sem::Type> sem::LocalScope::getType(const std::string& name)
 {
     return parentScope.getType(name);
 }
 
 
+std::optional<sem::Type> sem::LocalScope::getReturnableType(void)
+{
+    return returnType;
+}
+
+
 std::string sem::LocalScope::toString(void)
 {
     std::string ret;

+ 21 - 4
src/Scope.h

@@ -36,7 +36,8 @@ public:
     virtual ~Scope(void);
     virtual Variable* getVariable(const std::string& name) = 0;
     virtual Method* getMethod(const std::string& name) = 0;
-    virtual std::optional<Type*> getType(const std::string& name) = 0;
+    virtual std::optional<Type> getType(const std::string& name) = 0;
+    virtual std::optional<Type> getReturnableType(void) = 0;
 
     virtual std::string toString(void) = 0;
 };
@@ -49,7 +50,8 @@ public:
 public:
     virtual Variable* getVariable(const std::string& name);
     virtual Method* getMethod(const std::string& name);
-    virtual std::optional<Type*> getType(const std::string& name);
+    virtual std::optional<Type> getType(const std::string& name);
+    virtual std::optional<Type> getReturnableType(void);
 
     virtual std::string toString(void);
 };
@@ -66,7 +68,8 @@ public:
     }
     virtual Variable* getVariable(const std::string& name);
     virtual Method* getMethod(const std::string& name);
-    virtual std::optional<Type*> getType(const std::string& name);
+    virtual std::optional<Type> getType(const std::string& name);
+    virtual std::optional<Type> getReturnableType(void);
     virtual std::string toString(void);
 };
 
@@ -75,17 +78,31 @@ class qlow::sem::LocalScope : public Scope
 {
     Scope& parentScope;
     SymbolTable<Variable> localVariables;
+    Type returnType;
 public:
+    inline LocalScope(Scope& parentScope, const Type& returnType) :
+        parentScope{ parentScope }, returnType{ returnType }
+    {}
+
     inline LocalScope(Scope& parentScope) :
         parentScope{ parentScope }
     {
+        std::optional<Type> returnable = parentScope.getReturnableType();
+        if (returnable) {
+            returnType = returnable.value();
+        }
+        else {
+            returnType = Type(Type::Kind::NULL_TYPE);
+        }
     }
+
     void putVariable(const std::string& name, std::unique_ptr<Variable> v);
     SymbolTable<Variable>& getLocals(void);
 
     virtual Variable* getVariable(const std::string& name);
     virtual Method* getMethod(const std::string& name);
-    virtual std::optional<Type*> getType(const std::string& name);
+    virtual std::optional<Type> getType(const std::string& name);
+    virtual std::optional<Type> getReturnableType(void);
     virtual std::string toString(void);
 };
 

+ 6 - 6
src/Semantic.h

@@ -86,7 +86,7 @@ struct qlow::sem::Class : public SemanticObject
 
 struct qlow::sem::Variable : public SemanticObject
 {
-    Class* type;
+    Type type;
     std::string name;
 
     /// if this is a local variable, this stores a reference to the llvm
@@ -94,7 +94,7 @@ struct qlow::sem::Variable : public SemanticObject
     llvm::AllocaInst* allocaInst;
     
     Variable(void) = default;
-    inline Variable(Class* type, std::string& name) :
+    inline Variable(Type type, std::string& name) :
         type{ type }, name{ name }, allocaInst { nullptr } {}
         
     virtual std::string toString(void) const override;
@@ -103,7 +103,7 @@ struct qlow::sem::Variable : public SemanticObject
 
 struct qlow::sem::Field : public Variable
 {
-    Class* type;
+    Type type;
     std::string name;
     
     virtual std::string toString(void) const override;
@@ -113,7 +113,7 @@ struct qlow::sem::Field : public Variable
 struct qlow::sem::Method : public SemanticObject
 {
     Class* containingType;
-    std::unique_ptr<Type> returnType;
+    Type returnType;
     std::string name;
     ast::MethodDefinition* astNode;
     std::unique_ptr<DoEndBlock> body;
@@ -122,8 +122,8 @@ struct qlow::sem::Method : public SemanticObject
 
     llvm::Function* llvmNode;
 
-    inline Method(Scope& parentScope) :
-        scope{ parentScope } {}
+    inline Method(Scope& parentScope, const Type& returnType) :
+        returnType{ returnType }, scope{ parentScope } {}
     
     virtual std::string toString(void) const override;
 };

+ 16 - 5
src/Type.cpp

@@ -3,21 +3,32 @@
 
 using namespace qlow;
 
-sem::Type::~Type(void)
+sem::Type::Type(sem::Class* classType) :
+    kind{ Kind::CLASS }
 {
+    data.classType = classType;
 }
 
+bool sem::Type::isClassType(void) const
+{
+    return kind == Kind::CLASS;
+}
 
-bool sem::ClassType::isNative(void) const
+
+bool sem::Type::isNative(void) const
 {
-    return false;
+    return kind != Kind::CLASS;
 }
 
 
-bool sem::NativeType::isNative(void) const
+sem::Class* sem::Type::getClassType(void)
 {
-    return true;
+    if (kind != Kind::CLASS)
+        throw "internal error";
+    return data.classType;
 }
 
 
+const sem::Type sem::Type::INTEGER = sem::Type{ sem::Type::Kind::INTEGER };
+
 

+ 26 - 19
src/Type.h

@@ -6,16 +6,14 @@ namespace qlow
     namespace sem
     {
         // forward declarations
-        class Class;
+        struct Class;
+        struct NativeType;
     }
 
 
     namespace sem
     {
         class Type;
-
-        class ClassType;
-        class NativeType;
     }
 }
 
@@ -23,31 +21,40 @@ namespace qlow
 class qlow::sem::Type
 {
 public:
-    virtual ~Type(void);
+    enum class Kind
+    {
+        NULL_TYPE,
+        INTEGER,
+        CLASS,
+    };
 
-    virtual bool isNative(void) const = 0;
-};
+private:
+    union Data
+    {
+        Class* classType;
+    };
 
+    Kind kind;
+    Data data;
 
-class qlow::sem::ClassType : public Type
-{
-    Class* classType;
 public:
 
-    inline ClassType(Class* classType) :
-        classType{ classType } {}
+    inline Type(void) :
+        kind{ Kind::NULL_TYPE }, data{ nullptr } {}
 
-    Class* getClass(void) { return classType; }
+    Type(Class* classType);
 
-    virtual bool isNative(void) const;
-};
+    inline Type(Kind kind) :
+        kind{ kind }, data{ nullptr } {}
 
+    bool isClassType(void) const;
+    bool isNative(void) const;
 
-class qlow::sem::NativeType : public Type
-{
-public:
+    Class* getClassType(void);
+
+
+    static const Type INTEGER;
 
-    virtual bool isNative(void) const;
 };
 
 

+ 7 - 7
src/TypeVisitor.cpp

@@ -4,32 +4,32 @@ using namespace qlow;
 
 
 
-std::unique_ptr<sem::Type> sem::TypeVisitor::visit(sem::Expression& expr, const sem::SymbolTable<sem::Class>& classes)
+sem::Type sem::TypeVisitor::visit(sem::Expression& expr, const sem::SymbolTable<sem::Class>& classes)
 {
 }
 
 
-std::unique_ptr<sem::Type> sem::TypeVisitor::visit(sem::UnaryOperation& 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);
 }
 
 
-std::unique_ptr<sem::Type> sem::TypeVisitor::visit(sem::BinaryOperation& expr, const sem::SymbolTable<sem::Class>& classes)
+sem::Type sem::TypeVisitor::visit(sem::BinaryOperation& expr, const sem::SymbolTable<sem::Class>& classes)
 {
     return visit(*expr.left, classes);
 }
 
 
-std::unique_ptr<sem::Type> sem::TypeVisitor::visit(sem::FeatureCallExpression& expr, const sem::SymbolTable<sem::Class>& classes)
+sem::Type sem::TypeVisitor::visit(sem::FeatureCallExpression& expr, const sem::SymbolTable<sem::Class>& classes)
 {
-    return Type{ expr.callee->returnType };
+    return expr.callee->returnType;
 }
 
 
-std::unique_ptr<sem::Type> sem::TypeVisitor::visit(sem::IntConst& expr, const sem::SymbolTable<sem::Class>& classes)
+sem::Type sem::TypeVisitor::visit(sem::IntConst& expr, const sem::SymbolTable<sem::Class>& classes)
 {
-    return std::make_unique<NativeType>();
+    return Type::INTEGER;
 }
 
 

+ 6 - 6
src/TypeVisitor.h

@@ -15,7 +15,7 @@ namespace qlow
 
 class qlow::sem::TypeVisitor :
     public Visitor<
-        std::unique_ptr<qlow::sem::Type>,
+        qlow::sem::Type,
         const sem::SymbolTable<sem::Class>,
         
         sem::Expression,
@@ -27,11 +27,11 @@ class qlow::sem::TypeVisitor :
 {
     
 public:
-    std::unique_ptr<qlow::sem::Type> visit(sem::Expression& expr, const sem::SymbolTable<sem::Class>& classes) override;
-    std::unique_ptr<qlow::sem::Type> visit(sem::UnaryOperation& expr, const sem::SymbolTable<sem::Class>& classes) override;
-    std::unique_ptr<qlow::sem::Type> visit(sem::BinaryOperation& expr, const sem::SymbolTable<sem::Class>& classes) override;
-    std::unique_ptr<qlow::sem::Type> visit(sem::FeatureCallExpression& expr, const sem::SymbolTable<sem::Class>& classes) override;
-    std::unique_ptr<qlow::sem::Type> visit(sem::IntConst& 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