Ver Fonte

Merge branch 'master' of https://gitlab.vis.ethz.ch/niwinkle/qlow

Nicolas Winkler há 6 anos atrás
pai
commit
c7b71e2e98
16 ficheiros alterados com 190 adições e 210 exclusões
  1. 19 15
      src/AstVisitor.cpp
  2. 0 29
      src/AstVisitor.h
  3. 2 1
      src/Builtin.cpp
  4. 1 1
      src/CodeGeneration.cpp
  5. 1 1
      src/CodeGeneration.h
  6. 17 10
      src/CodegenVisitor.cpp
  7. 4 2
      src/CodegenVisitor.h
  8. 12 12
      src/Scope.cpp
  9. 13 13
      src/Scope.h
  10. 6 5
      src/Semantic.cpp
  11. 56 26
      src/Semantic.h
  12. 25 9
      src/Type.cpp
  13. 33 9
      src/Type.h
  14. 0 39
      src/TypeVisitor.cpp
  15. 0 37
      src/TypeVisitor.h
  16. 1 1
      src/test.qlw

+ 19 - 15
src/AstVisitor.cpp

@@ -29,7 +29,7 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FieldDeclarati
 {
     auto f = std::make_unique<sem::Field>();
     f->name = ast.name;
-    auto* type = scope.getType(*ast.type);
+    auto type = scope.getType(*ast.type);
     if (type) {
         f->type = type;
     }
@@ -79,9 +79,9 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::VariableDeclar
 {
     auto v = std::make_unique<sem::Variable>();
     v->name = ast.name;
-    auto* type = scope.getType(*ast.type);
+    auto type = scope.getType(*ast.type);
     if (type) {
-        v->type = type;
+        v->type = std::move(type);
     }
     else {
         throw SemanticError(SemanticError::UNKNOWN_TYPE,
@@ -107,13 +107,13 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::DoEndBlock& as
     for (auto& statement : ast.statements) {
         
         if (ast::LocalVariableStatement* nvs = dynamic_cast<ast::LocalVariableStatement*>(statement.get()); nvs) {
-            auto* type = body->scope.getType(*nvs->type);
+            auto type = body->scope.getType(*nvs->type);
 
             if (!type)
                 throw SemanticError(SemanticError::UNKNOWN_TYPE,
                                     nvs->type->asString(),
                                     nvs->type->pos);
-            auto var = std::make_unique<sem::Variable>(type, nvs->name);
+            auto var = std::make_unique<sem::Variable>(std::move(type), nvs->name);
             body->scope.putVariable(nvs->name, std::move(var));
             continue;
         }
@@ -188,12 +188,10 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureCall& a
     auto* var = scope.getVariable(ast.name);
     
     if (var) {
-        auto lve = std::make_unique<sem::LocalVariableExpression>();
-        lve->var = var;
-        return lve;
+        return std::make_unique<sem::LocalVariableExpression>(var);
     }
     else if (method) {
-        auto fce = std::make_unique<sem::FeatureCallExpression>();
+        auto fce = std::make_unique<sem::FeatureCallExpression>(method->returnType);
         for (auto& arg : ast.arguments) {
             auto argument = arg->accept(*this, scope);
             if (dynamic_cast<sem::Expression*>(argument.get())) {
@@ -250,27 +248,33 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::IntConst& ast,
 
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::UnaryOperation& ast, sem::Scope& scope)
 {
-    auto ret = std::make_unique<sem::UnaryOperation>();
+    auto argument = unique_dynamic_cast<sem::Expression>(ast.expr->accept(*this, scope));
+    auto ret = std::make_unique<sem::UnaryOperation>(argument->type);
+            // TODO not a feasible assumption
     ret->op = ast.op;
     ret->side = ast.side;
-    ret->arg = unique_dynamic_cast<sem::Expression>(ast.expr->accept(*this, scope));
+    ret->arg = std::move(argument);
     return ret;
 }
 
 
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::BinaryOperation& ast, sem::Scope& scope)
 {
-    auto ret = std::make_unique<sem::BinaryOperation>();
+    auto leftEval = unique_dynamic_cast<sem::Expression>(ast.left->accept(*this, scope));
+    auto rightEval = unique_dynamic_cast<sem::Expression>(ast.right->accept(*this, scope));
+    
+    auto ret = std::make_unique<sem::BinaryOperation>(leftEval->type);
+    
     ret->op = ast.op;
-    ret->left = unique_dynamic_cast<sem::Expression>(ast.left->accept(*this, scope));
-    ret->right = unique_dynamic_cast<sem::Expression>(ast.right->accept(*this, scope));
+    ret->left = std::move(leftEval);
+    ret->right = std::move(rightEval);
     return ret;
 }
 
 
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::NewArrayExpression& ast, sem::Scope& scope)
 {
-    auto ret = std::make_unique<sem::BinaryOperation>();
+    auto ret = std::make_unique<sem::NewArrayExpression>(scope.getType(*ast.type));
     return ret;
 }
 

+ 0 - 29
src/AstVisitor.h

@@ -16,35 +16,6 @@ namespace qlow
     {
         template<typename T>
         using List = std::vector<std::unique_ptr<T>>;
-
-        // base class
-        struct AstObject;
-
-        struct Class;
-
-        struct FeatureDeclaration;
-
-        struct FieldDeclaration;
-        struct MethodDefinition;
-
-        struct VariableDeclaration;
-        struct ArgumentDeclaration;
-
-        struct DoEndBlock;
-
-        struct Statement;
-        struct Expression;
-
-        struct FeatureCall;
-        struct AssignmentStatement;
-        struct LocalVariableStatement;
-        struct IntConst;
-
-        struct Operation;
-        struct UnaryOperation;
-        struct BinaryOperation;
-        
-        struct NewArrayExpression;
     }
 }
 

+ 2 - 1
src/Builtin.cpp

@@ -36,7 +36,8 @@ sem::NativeScope qlow::sem::generateNativeScope(void)
     };
     
     for (auto [name, type] : natives) {
-        scope.types.insert({ name, std::make_unique<NativeType>(type) });
+        scope.types.insert({ name, std::make_unique
+            <std::shared_ptr<NativeType>>(std::make_shared<NativeType>(type)) });
     }
     
     return scope;

+ 1 - 1
src/CodeGeneration.cpp

@@ -273,7 +273,7 @@ llvm::Function* qlow::gen::FunctionGenerator::generate(void)
     //Value* val = llvm::ConstantFP::get(context, llvm::APFloat(5.0));
     
     builder.SetInsertPoint(getCurrentBlock());
-    if (method.returnType->equals(sem::Type::VOID)) {
+    if (method.returnType->equals(*sem::Type::VOID)) {
         if (!getCurrentBlock()->getTerminator())
             builder.CreateRetVoid();
     }

+ 1 - 1
src/CodeGeneration.h

@@ -30,7 +30,7 @@ class qlow::gen::FunctionGenerator
 public:
 
     StatementVisitor statementVisitor;
-    ExpressionVisitor expressionVisitor;
+    ExpressionCodegenVisitor expressionVisitor;
 
     inline FunctionGenerator(const sem::Method& m, llvm::Module* module) :
         method{ m }, module{ module }

+ 17 - 10
src/CodegenVisitor.cpp

@@ -9,20 +9,20 @@
 
 using namespace qlow;
 
-std::pair<llvm::Value*, sem::Type*> ExpressionVisitor::visit(sem::LocalVariableExpression& lve, llvm::IRBuilder<>& builder)
+std::pair<llvm::Value*, sem::Type*> ExpressionCodegenVisitor::visit(sem::LocalVariableExpression& lve, llvm::IRBuilder<>& builder)
 {
     assert(lve.var->allocaInst != nullptr);
     if (llvm::dyn_cast<llvm::AllocaInst>(lve.var->allocaInst)) {
         llvm::Value* val = builder.CreateLoad(lve.var->allocaInst);
-        return { val, lve.var->type };
+        return { val, lve.var->type.get() };
     }
     else {
-        return { lve.var->allocaInst, lve.var->type };
+        return { lve.var->allocaInst, lve.var->type.get() };
     }
 }
 
 
-std::pair<llvm::Value*, sem::Type*> ExpressionVisitor::visit(sem::BinaryOperation& binop, llvm::IRBuilder<>& builder)
+std::pair<llvm::Value*, sem::Type*> ExpressionCodegenVisitor::visit(sem::BinaryOperation& binop, llvm::IRBuilder<>& builder)
 {
     using llvm::Value;
     using sem::Type;
@@ -40,7 +40,7 @@ std::pair<llvm::Value*, sem::Type*> ExpressionVisitor::visit(sem::BinaryOperatio
     
     
     Value* implicitelyCastedRight = right;
-    if (!leftType->equals(rightType))
+    if (!leftType->equals(*rightType))
         implicitelyCastedRight = dynamic_cast<sem::NativeType*>(leftType)->generateImplicitCast(right);
     
     if (dynamic_cast<sem::NativeType*>(leftType)->isIntegerType()) {
@@ -74,7 +74,7 @@ std::pair<llvm::Value*, sem::Type*> ExpressionVisitor::visit(sem::BinaryOperatio
 }
 
 
-std::pair<llvm::Value*, sem::Type*> ExpressionVisitor::visit(sem::UnaryOperation& unop, llvm::IRBuilder<>& builder)
+std::pair<llvm::Value*, sem::Type*> ExpressionCodegenVisitor::visit(sem::UnaryOperation& unop, llvm::IRBuilder<>& builder)
 {
     using llvm::Value;
     auto [value, type] = unop.arg->accept(*this, builder);
@@ -92,7 +92,14 @@ std::pair<llvm::Value*, sem::Type*> ExpressionVisitor::visit(sem::UnaryOperation
     }
 }
 
-std::pair<llvm::Value*, sem::Type*> ExpressionVisitor::visit(sem::FeatureCallExpression& call, llvm::IRBuilder<>& builder)
+
+std::pair<llvm::Value*, sem::Type*> ExpressionCodegenVisitor::visit(sem::NewArrayExpression& naexpr, llvm::IRBuilder<>& builder)
+{
+    using llvm::Value;
+    // TODO implement
+}
+
+std::pair<llvm::Value*, sem::Type*> ExpressionCodegenVisitor::visit(sem::FeatureCallExpression& call, llvm::IRBuilder<>& builder)
 {
     using llvm::Value;
     std::vector<Value*> arguments;
@@ -104,7 +111,7 @@ std::pair<llvm::Value*, sem::Type*> ExpressionVisitor::visit(sem::FeatureCallExp
         auto& arg = call.arguments[i];
         auto [value, type] = arg->accept(*this, builder);
         
-        if (!type->equals(call.callee->arguments[i]->type)) {
+        if (!type->equals(*call.callee->arguments[i]->type.get())) {
             throw "argument type mismatch";
         }
         
@@ -113,11 +120,11 @@ std::pair<llvm::Value*, sem::Type*> ExpressionVisitor::visit(sem::FeatureCallExp
     auto returnType = call.callee->returnType;
     llvm::CallInst* callInst = builder.CreateCall(call.callee->llvmNode, arguments);
     
-    return { callInst, returnType };
+    return { callInst, returnType.get() };
     //return { nullptr, sem::Type::NULL_TYPE };
 }
 
-std::pair<llvm::Value*, sem::Type*> ExpressionVisitor::visit(sem::IntConst& node, llvm::IRBuilder<>& builder)
+std::pair<llvm::Value*, sem::Type*> ExpressionCodegenVisitor::visit(sem::IntConst& node, llvm::IRBuilder<>& builder)
 {
     return {
         llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, std::to_string(node.value), 10)),

+ 4 - 2
src/CodegenVisitor.h

@@ -25,12 +25,12 @@ namespace qlow
 
 namespace qlow
 {
-    class ExpressionVisitor;
+    class ExpressionCodegenVisitor;
     class StatementVisitor;
 }
 
 
-class qlow::ExpressionVisitor :
+class qlow::ExpressionCodegenVisitor :
     public Visitor<
         std::pair<llvm::Value*, sem::Type*>,
         llvm::IRBuilder<>,
@@ -38,6 +38,7 @@ class qlow::ExpressionVisitor :
         sem::LocalVariableExpression,
         sem::BinaryOperation,
         sem::UnaryOperation,
+        sem::NewArrayExpression,
         sem::FeatureCallExpression,
         sem::IntConst
     >
@@ -46,6 +47,7 @@ public:
     std::pair<llvm::Value*, sem::Type*> visit(sem::LocalVariableExpression& node, llvm::IRBuilder<>&) override;
     std::pair<llvm::Value*, sem::Type*> visit(sem::BinaryOperation& node, llvm::IRBuilder<>&) override;
     std::pair<llvm::Value*, sem::Type*> visit(sem::UnaryOperation& node, llvm::IRBuilder<>&) override;
+    std::pair<llvm::Value*, sem::Type*> visit(sem::NewArrayExpression& node, llvm::IRBuilder<>&) override;
     std::pair<llvm::Value*, sem::Type*> visit(sem::FeatureCallExpression& node, llvm::IRBuilder<>&) override;
     std::pair<llvm::Value*, sem::Type*> visit(sem::IntConst& node, llvm::IRBuilder<>&) override;
 };

+ 12 - 12
src/Scope.cpp

@@ -26,10 +26,10 @@ sem::Method* sem::GlobalScope::getMethod(const std::string& name)
 }
 
 
-sem::Type* sem::GlobalScope::getType(const ast::Type& name)
+std::shared_ptr<sem::Type> sem::GlobalScope::getType(const ast::Type& name)
 {
     if (const auto* arr = dynamic_cast<const ast::ArrayType*>(&name); arr) {
-        return new sem::ArrayType(getType(*arr->arrayType));
+        return std::make_unique<sem::ArrayType>(getType(*arr->arrayType));
     }
     
     auto native = NativeScope::getInstance().getType(name);
@@ -46,13 +46,13 @@ sem::Type* sem::GlobalScope::getType(const ast::Type& name)
     
     auto t = classes.find(classType->typeName);
     if (t != classes.end())
-        return new sem::ClassType(t->second.get());
+        return std::make_shared<sem::ClassType>(t->second.get());
     
     return nullptr;
 }
 
 
-sem::Type* sem::GlobalScope::getReturnableType(void)
+std::shared_ptr<sem::Type> sem::GlobalScope::getReturnableType(void)
 {
     return nullptr;
 }
@@ -70,21 +70,21 @@ std::string sem::GlobalScope::toString(void)
 }
 
 
-sem::Type* sem::NativeScope::getType(const ast::Type& name)
+std::shared_ptr<sem::Type> sem::NativeScope::getType(const ast::Type& name)
 {
     if (const auto* arr = dynamic_cast<const ast::ArrayType*>(&name); arr) {
-        return new sem::ArrayType(getType(*arr->arrayType));
+        return std::make_shared<sem::ArrayType>(getType(*arr->arrayType));
     }
     
     const auto* classType = dynamic_cast<const ast::ClassType*>(&name);
    
     if (!classType)
-        return sem::Type::VOID;
+        return std::make_shared<sem::NativeType>(NativeType::VOID);
     
     
     auto t = types.find(classType->typeName);
     if (t != types.end())
-        return t->second.get();
+        return *t->second;
     
     return nullptr;
 }
@@ -143,13 +143,13 @@ std::string sem::ClassScope::toString(void)
 }
 
 
-sem::Type* sem::ClassScope::getType(const ast::Type& name)
+std::shared_ptr<sem::Type> sem::ClassScope::getType(const ast::Type& name)
 {
     return parentScope.getType(name);
 }
 
 
-sem::Type* sem::ClassScope::getReturnableType(void)
+std::shared_ptr<sem::Type> sem::ClassScope::getReturnableType(void)
 {
     return nullptr;
 }
@@ -183,13 +183,13 @@ sem::Method* sem::LocalScope::getMethod(const std::string& name)
 }
 
 
-sem::Type* sem::LocalScope::getType(const ast::Type& name)
+std::shared_ptr<sem::Type> sem::LocalScope::getType(const ast::Type& name)
 {
     return parentScope.getType(name);
 }
 
 
-sem::Type* sem::LocalScope::getReturnableType(void)
+std::shared_ptr<sem::Type> sem::LocalScope::getReturnableType(void)
 {
     return returnType;
 }

+ 13 - 13
src/Scope.h

@@ -43,8 +43,8 @@ public:
     virtual ~Scope(void);
     virtual Variable* getVariable(const std::string& name) = 0;
     virtual Method* getMethod(const std::string& name) = 0;
-    virtual Type* getType(const ast::Type& name) = 0;
-    virtual Type* getReturnableType(void) = 0;
+    virtual std::shared_ptr<Type> getType(const ast::Type& name) = 0;
+    virtual std::shared_ptr<Type> getReturnableType(void) = 0;
 
     virtual std::string toString(void) = 0;
 };
@@ -58,8 +58,8 @@ public:
 public:
     virtual Variable* getVariable(const std::string& name);
     virtual Method* getMethod(const std::string& name);
-    virtual Type* getType(const ast::Type& name);
-    virtual Type* getReturnableType(void);
+    virtual std::shared_ptr<Type> getType(const ast::Type& name);
+    virtual std::shared_ptr<Type> getReturnableType(void);
 
     virtual std::string toString(void);
 };
@@ -69,9 +69,9 @@ class qlow::sem::NativeScope : public GlobalScope
 {
     static NativeScope instance;
 public:
-    SymbolTable<NativeType> types;
+    SymbolTable<std::shared_ptr<NativeType>> types;
 public:
-    virtual Type* getType(const ast::Type& name);
+    virtual std::shared_ptr<Type> getType(const ast::Type& name);
 
     virtual std::string toString(void);
     
@@ -91,8 +91,8 @@ public:
     }
     virtual Variable* getVariable(const std::string& name);
     virtual Method* getMethod(const std::string& name);
-    virtual Type* getType(const ast::Type& name);
-    virtual Type* getReturnableType(void);
+    virtual std::shared_ptr<Type> getType(const ast::Type& name);
+    virtual std::shared_ptr<Type> getReturnableType(void);
     virtual std::string toString(void);
 };
 
@@ -101,7 +101,7 @@ class qlow::sem::LocalScope : public Scope
 {
     Scope& parentScope;
     SymbolTable<Variable> localVariables;
-    Type* returnType;
+    std::shared_ptr<Type> returnType;
 public:
     inline LocalScope(Scope& parentScope, Type* returnType) :
         parentScope{ parentScope },
@@ -112,9 +112,9 @@ public:
     inline LocalScope(Scope& parentScope) :
         parentScope{ parentScope }
     {
-        Type* returnable = parentScope.getReturnableType();
+        auto returnable = parentScope.getReturnableType();
         if (returnable) {
-            returnType = returnable;
+            returnType = std::move(returnable);
         }
         else {
             returnType = nullptr;
@@ -126,8 +126,8 @@ public:
 
     virtual Variable* getVariable(const std::string& name);
     virtual Method* getMethod(const std::string& name);
-    virtual Type* getType(const ast::Type& name);
-    virtual Type* getReturnableType(void);
+    virtual std::shared_ptr<Type> getType(const ast::Type& name);
+    virtual std::shared_ptr<Type> getReturnableType(void);
     virtual std::string toString(void);
 };
 

+ 6 - 5
src/Semantic.cpp

@@ -169,11 +169,12 @@ ReturnType ClassName::accept(Visitor& v, Arg arg) \
     return v.visit(*this, arg); \
 }
 
-ACCEPT_DEFINITION(LocalVariableExpression, ExpressionVisitor, std::pair<llvm::Value* COMMA Type*>, llvm::IRBuilder<>&)
-ACCEPT_DEFINITION(BinaryOperation, ExpressionVisitor, std::pair<llvm::Value* COMMA Type*>, llvm::IRBuilder<>&)
-ACCEPT_DEFINITION(UnaryOperation, ExpressionVisitor, std::pair<llvm::Value* COMMA Type*>, llvm::IRBuilder<>&)
-ACCEPT_DEFINITION(FeatureCallExpression, ExpressionVisitor, std::pair<llvm::Value* COMMA Type*>, llvm::IRBuilder<>&)
-ACCEPT_DEFINITION(IntConst, ExpressionVisitor, std::pair<llvm::Value* COMMA Type*>, llvm::IRBuilder<>&)
+ACCEPT_DEFINITION(LocalVariableExpression, ExpressionCodegenVisitor, std::pair<llvm::Value* COMMA Type*>, llvm::IRBuilder<>&)
+ACCEPT_DEFINITION(BinaryOperation, ExpressionCodegenVisitor, std::pair<llvm::Value* COMMA Type*>, llvm::IRBuilder<>&)
+ACCEPT_DEFINITION(NewArrayExpression, ExpressionCodegenVisitor, std::pair<llvm::Value* COMMA Type*>, llvm::IRBuilder<>&)
+ACCEPT_DEFINITION(UnaryOperation, ExpressionCodegenVisitor, std::pair<llvm::Value* COMMA Type*>, llvm::IRBuilder<>&)
+ACCEPT_DEFINITION(FeatureCallExpression, ExpressionCodegenVisitor, std::pair<llvm::Value* COMMA Type*>, llvm::IRBuilder<>&)
+ACCEPT_DEFINITION(IntConst, ExpressionCodegenVisitor, std::pair<llvm::Value* COMMA Type*>, llvm::IRBuilder<>&)
 
 ACCEPT_DEFINITION(AssignmentStatement, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&) 
 ACCEPT_DEFINITION(DoEndBlock, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&) 

+ 56 - 26
src/Semantic.h

@@ -8,6 +8,8 @@
 #include "Visitor.h"
 #include "Scope.h"
 
+#include "Type.h"
+
 #include <llvm/IR/Value.h>
 #include <llvm/IR/IRBuilder.h>
 #include <llvm/IR/BasicBlock.h>
@@ -19,7 +21,6 @@ namespace qlow
         std::unique_ptr<GlobalScope>
             createFromAst(const std::vector<std::unique_ptr<qlow::ast::AstObject>>& objects);
 
-        struct SemanticObject;
         struct Class;
 
         struct Variable;
@@ -52,7 +53,7 @@ namespace qlow
         class SemanticException;
     }
 
-    class ExpressionVisitor;
+    class ExpressionCodegenVisitor;
     class StatementVisitor;
 
     namespace gen
@@ -62,17 +63,6 @@ namespace qlow
 }
 
 
-struct qlow::sem::SemanticObject
-{
-    virtual ~SemanticObject(void);
-    
-    /**
-     * \brief converts the object to a readable string for debugging purposes. 
-     */
-    virtual std::string toString(void) const;
-};
-
-
 struct qlow::sem::Class : public SemanticObject
 {
     qlow::ast::Class* astNode;
@@ -106,7 +96,7 @@ struct qlow::sem::Class : public SemanticObject
 
 struct qlow::sem::Variable : public SemanticObject
 {
-    Type* type;
+    std::shared_ptr<Type> type;
     std::string name;
 
     /// if this is a local variable, this stores a reference to the llvm
@@ -114,8 +104,8 @@ struct qlow::sem::Variable : public SemanticObject
     llvm::Value* allocaInst;
     
     Variable(void) = default;
-    inline Variable(Type* type, std::string& name) :
-        type{ type }, name{ name }, allocaInst { nullptr } {}
+    inline Variable(std::shared_ptr<Type> type, std::string& name) :
+        type{ std::move(type) }, name{ name }, allocaInst { nullptr } {}
         
     virtual std::string toString(void) const override;
 };
@@ -130,7 +120,7 @@ struct qlow::sem::Field : public Variable
 struct qlow::sem::Method : public SemanticObject
 {
     Class* containingType;
-    Type* returnType;
+    std::shared_ptr<Type> returnType;
     std::vector<Variable*> arguments;
     std::string name;
     ast::MethodDefinition* astNode;
@@ -140,8 +130,8 @@ struct qlow::sem::Method : public SemanticObject
 
     llvm::Function* llvmNode;
 
-    inline Method(Scope& parentScope, Type* returnType) :
-        returnType{ returnType },
+    inline Method(Scope& parentScope, std::shared_ptr<Type> returnType) :
+        returnType{ std::move(returnType) },
         scope{ parentScope },
         body{ nullptr }
     {
@@ -233,22 +223,39 @@ struct qlow::sem::Expression :
     public SemanticObject,
     public Visitable<std::pair<llvm::Value*, sem::Type*>,
                      llvm::IRBuilder<>,
-                     qlow::ExpressionVisitor>
+                     qlow::ExpressionCodegenVisitor>
 {
+    std::shared_ptr<sem::Type> type;
+    
+    inline Expression(std::shared_ptr<Type> type) :
+        type{ std::move(type) }
+    {
+    }
 };
 
 
 struct qlow::sem::Operation : public Expression
 {
     ast::Operation::Operator op;
+    
+    inline Operation(std::shared_ptr<Type> type) :
+        Expression{ std::move(type) }
+    {
+    }
 };
 
 
 struct qlow::sem::LocalVariableExpression : public Expression
 {
     Variable* var;
+    
+    inline LocalVariableExpression(Variable* var) :
+        Expression{ var->type },
+        var{ var }
+    {
+    }
 
-    virtual std::pair<llvm::Value*, sem::Type*> accept(ExpressionVisitor& visitor, llvm::IRBuilder<>& arg2) override;
+    virtual std::pair<llvm::Value*, sem::Type*> accept(ExpressionCodegenVisitor& visitor, llvm::IRBuilder<>& arg2) override;
     virtual std::string toString(void) const override;
 };
 
@@ -258,7 +265,12 @@ struct qlow::sem::BinaryOperation : public Operation
     std::unique_ptr<Expression> left;
     std::unique_ptr<Expression> right;
     
-    virtual std::pair<llvm::Value*, sem::Type*> accept(ExpressionVisitor& visitor, llvm::IRBuilder<>& arg2) override;
+    inline BinaryOperation(std::shared_ptr<Type> type) :
+        Operation{ std::move(type) }
+    {
+    }
+    
+    virtual std::pair<llvm::Value*, sem::Type*> accept(ExpressionCodegenVisitor& visitor, llvm::IRBuilder<>& arg2) override;
     
     virtual std::string toString(void) const override;
 };
@@ -269,7 +281,12 @@ struct qlow::sem::NewArrayExpression : public Expression
     std::unique_ptr<Type> arrayType;
     std::unique_ptr<Expression> length;
     
-    virtual std::pair<llvm::Value*, sem::Type*> accept(ExpressionVisitor& visitor, llvm::IRBuilder<>& arg2) override;
+    inline NewArrayExpression(std::shared_ptr<Type> type) :
+        Expression{ std::move(type) }
+    {
+    }
+    
+    virtual std::pair<llvm::Value*, sem::Type*> accept(ExpressionCodegenVisitor& visitor, llvm::IRBuilder<>& arg2) override;
     virtual std::string toString(void) const override;
 };
 
@@ -278,7 +295,13 @@ struct qlow::sem::UnaryOperation : public Operation
 {
     qlow::ast::UnaryOperation::Side side;
     std::unique_ptr<Expression> arg;
-    virtual std::pair<llvm::Value*, sem::Type*> accept(ExpressionVisitor& visitor, llvm::IRBuilder<>& arg2) override;
+    
+    inline UnaryOperation(std::shared_ptr<Type> type) :
+        Operation{ std::move(type) }
+    {
+    }
+    
+    virtual std::pair<llvm::Value*, sem::Type*> accept(ExpressionCodegenVisitor& visitor, llvm::IRBuilder<>& arg2) override;
     virtual std::string toString(void) const override;
 };
 
@@ -287,7 +310,13 @@ struct qlow::sem::FeatureCallExpression : public Expression
 {
     Method* callee;
     OwningList<Expression> arguments;
-    virtual std::pair<llvm::Value*, sem::Type*> accept(ExpressionVisitor& visitor, llvm::IRBuilder<>& arg2) override;
+    
+    inline FeatureCallExpression(std::shared_ptr<Type> type) :
+        Expression{ std::move(type) }
+    {
+    }
+    
+    virtual std::pair<llvm::Value*, sem::Type*> accept(ExpressionCodegenVisitor& visitor, llvm::IRBuilder<>& arg2) override;
     
     virtual std::string toString(void) const override;
 };
@@ -298,11 +327,12 @@ struct qlow::sem::IntConst : public Expression
     unsigned long long value;
 
     inline IntConst(unsigned long long value) :
+        Expression{ std::make_shared<NativeType>(NativeType::INTEGER) },
         value{ value }
     {
     }
     
-    virtual std::pair<llvm::Value*, sem::Type*> accept(ExpressionVisitor& visitor, llvm::IRBuilder<>& arg2) override;
+    virtual std::pair<llvm::Value*, sem::Type*> accept(ExpressionCodegenVisitor& visitor, llvm::IRBuilder<>& arg2) override;
 };
 
 

+ 25 - 9
src/Type.cpp

@@ -15,9 +15,9 @@ sem::Type::~Type(void)
 }
 
 
-bool sem::Type::equals(const Type* other) const
+bool sem::Type::equals(const Type& other) const
 {
-    return this == other;
+    return this == &other;
 }
 
 
@@ -26,15 +26,21 @@ sem::Type* sem::Type::INTEGER = new sem::NativeType(sem::NativeType::Type::INTEG
 sem::Type* sem::Type::BOOLEAN = new sem::NativeType(sem::NativeType::Type::BOOLEAN);
 
 
+sem::Scope& sem::ClassType::getScope(void)
+{
+    return classType->scope;
+}
+
+
 llvm::Type* sem::ClassType::getLlvmType (llvm::LLVMContext& context) const
 {
     return classType->llvmType;
 }
 
 
-bool sem::ClassType::equals(const Type* other) const
+bool sem::ClassType::equals(const Type& other) const
 {
-    if (auto* oct = dynamic_cast<const ClassType*>(other); oct) {
+    if (auto* oct = dynamic_cast<const ClassType*>(&other); oct) {
         return this->classType == oct->classType;
     }
     else {
@@ -43,6 +49,11 @@ bool sem::ClassType::equals(const Type* other) const
 }
 
 
+sem::Scope& sem::ArrayType::getScope(void)
+{
+}
+
+
 llvm::Type* sem::ArrayType::getLlvmType (llvm::LLVMContext& context) const
 {
     // TODO implement
@@ -50,10 +61,10 @@ llvm::Type* sem::ArrayType::getLlvmType (llvm::LLVMContext& context) const
 }
 
 
-bool sem::ArrayType::equals(const Type* other) const
+bool sem::ArrayType::equals(const Type& other) const
 {
-    if (auto* oct = dynamic_cast<const ArrayType*>(other); oct) {
-        return this->arrayType->equals(oct->arrayType);
+    if (auto* oct = dynamic_cast<const ArrayType*>(&other); oct) {
+        return this->arrayType->equals(*oct->arrayType);
     }
     else {
         return false;
@@ -61,6 +72,11 @@ bool sem::ArrayType::equals(const Type* other) const
 }
 
 
+sem::Scope& sem::NativeType::getScope(void)
+{
+}
+
+
 bool sem::NativeType::isIntegerType(void) const
 {
     switch(type) {
@@ -126,9 +142,9 @@ llvm::Type* sem::NativeType::getLlvmType (llvm::LLVMContext& context) const
 }
 
 
-bool sem::NativeType::equals(const sem::Type* other) const
+bool sem::NativeType::equals(const sem::Type& other) const
 {
-    if (auto* oct = dynamic_cast<const NativeType*>(other); oct) {
+    if (auto* oct = dynamic_cast<const NativeType*>(&other); oct) {
         return this->type == oct->type;
     }
     else {

+ 33 - 9
src/Type.h

@@ -2,9 +2,9 @@
 #define QLOW_SEM_TYPE_H
 
 #include <memory>
-#include "Semantic.h"
 
 namespace llvm {
+    class Value;
     class Type;
     class LLVMContext;
 }
@@ -15,11 +15,15 @@ namespace qlow
     {
         // forward declarations
         struct Class;
+        
+        class Scope;
     }
 
 
     namespace sem
     {
+        struct SemanticObject;
+        
         class Type;
         
         class ClassType;
@@ -29,6 +33,18 @@ namespace qlow
 }
 
 
+struct qlow::sem::SemanticObject
+{
+    virtual ~SemanticObject(void);
+    
+    /**
+     * \brief converts the object to a readable string for debugging purposes. 
+     */
+    virtual std::string toString(void) const;
+};
+
+
+
 class qlow::sem::Type : public SemanticObject
 {
 public:
@@ -38,9 +54,11 @@ public:
     virtual bool isNativeType(void) const = 0;
     virtual bool isArrayType(void) const = 0;
 
+    virtual Scope& getScope(void) = 0;
+    
     virtual llvm::Type* getLlvmType(llvm::LLVMContext& context) const = 0;
     
-    virtual bool equals(const Type* other) const;
+    virtual bool equals(const Type& other) const;
     
     static Type* VOID;
     static Type* INTEGER;
@@ -61,19 +79,21 @@ public:
     inline bool isNativeType(void) const override { return false; }
     inline bool isArrayType(void) const override { return false; }
     
+    Scope& getScope(void);
+    
     virtual llvm::Type* getLlvmType(llvm::LLVMContext& context) const override;
     inline sem::Class* getClassType(void) { return classType; }
-    virtual bool equals(const Type* other) const;
+    virtual bool equals(const Type& other) const;
 };
 
 
 class qlow::sem::ArrayType : public Type
 {
-    sem::Type* arrayType;
+    std::shared_ptr<sem::Type> arrayType;
 public:
     
-    inline ArrayType(sem::Type* arrayType) :
-        arrayType{ arrayType }
+    inline ArrayType(std::shared_ptr<sem::Type> arrayType) :
+        arrayType{ std::move(arrayType) }
     {
     }
     
@@ -81,9 +101,11 @@ public:
     inline bool isNativeType(void) const override { return false; }
     inline bool isArrayType(void) const override { return true; }
     
+    Scope& getScope(void);
+    
     virtual llvm::Type* getLlvmType(llvm::LLVMContext& context) const override;
-    inline sem::Type* getArrayType(void) { return arrayType; }
-    virtual bool equals(const Type* other) const;
+    inline std::shared_ptr<sem::Type> getArrayType(void) { return arrayType; }
+    virtual bool equals(const Type& other) const;
 };
 
 
@@ -112,10 +134,12 @@ public:
     inline bool isNativeType(void) const override { return true; }
     inline bool isArrayType(void) const override { return false; }
     
+    Scope& getScope(void);
+    
     bool isIntegerType(void) const;
     
     llvm::Type* getLlvmType(llvm::LLVMContext& context) const override;
-    virtual bool equals(const sem::Type* other) const;
+    virtual bool equals(const sem::Type& other) const;
     
     /// cast an llvm::Value from another native type to this one
     llvm::Value* generateImplicitCast(llvm::Value* value);

+ 0 - 39
src/TypeVisitor.cpp

@@ -1,39 +0,0 @@
-#include "TypeVisitor.h"
-#include "Type.h"
-
-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 expr.callee->returnType;
-}
-
-
-sem::Type* sem::TypeVisitor::visit(sem::IntConst& expr, const sem::SymbolTable<sem::Class>& classes)
-{
-    return Type::INTEGER;
-}
-
-
-
-
-

+ 0 - 37
src/TypeVisitor.h

@@ -1,37 +0,0 @@
-#ifndef QLOW_SEM_TYPEVISITOR_H
-#define QLOW_SEM_TYPEVISITOR_H
-
-#include "Visitor.h"
-#include "Semantic.h"
-
-namespace qlow
-{
-    namespace sem
-    {
-        class TypeVisitor;
-    }
-}
-
-
-class qlow::sem::TypeVisitor :
-    public Visitor<
-        qlow::sem::Type*,
-        const sem::SymbolTable<sem::Class>,
-
-        sem::Expression,
-        sem::UnaryOperation,
-        sem::BinaryOperation,
-        sem::FeatureCallExpression,
-        sem::IntConst
-    >
-{
-
-public:
-    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/test.qlw

@@ -23,7 +23,7 @@ bignumbers do
     b: Int128
     c: Int64
 
-    b := a + c
+    //b := a + c
 end
 
 main do