Nicolas Winkler 6 سال پیش
والد
کامیت
a23953029e
12فایلهای تغییر یافته به همراه288 افزوده شده و 44 حذف شده
  1. 3 0
      src/AstVisitor.cpp
  2. 18 9
      src/CodeGeneration.cpp
  3. 4 1
      src/CodeGeneration.h
  4. 112 7
      src/CodegenVisitor.cpp
  5. 27 0
      src/CodegenVisitor.h
  6. 2 0
      src/Scope.cpp
  7. 24 3
      src/Semantic.cpp
  8. 25 8
      src/Semantic.h
  9. 28 0
      src/Type.cpp
  10. 36 9
      src/Type.h
  11. 3 3
      src/makefile
  12. 6 4
      src/tests/structs.qlw

+ 3 - 0
src/AstVisitor.cpp

@@ -61,6 +61,7 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::MethodDefiniti
         if (dynamic_cast<sem::Variable*>(var.get())) {
             std::unique_ptr<sem::Variable> variable =
                 unique_dynamic_cast<sem::Variable>(std::move(var));
+            variable->isParameter = true;
             m->arguments.push_back(variable.get());
             std::string varname = variable->name;
             m->scope.putVariable(varname, std::move(variable));
@@ -241,9 +242,11 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureCall& a
             auto* thisExpr = scope.getVariable("this");
             if (!thisExpr)
                 throw "no this found";
+            Logger::getInstance().debug() << "feature call " << var->toString() << " is a field\n";
             return std::make_unique<sem::FieldAccessExpression>(std::make_unique<sem::LocalVariableExpression>(thisExpr), field);
         }
         else {
+            Logger::getInstance().debug() << "feature call " << var->toString() << " is not a field\n";
             return std::make_unique<sem::LocalVariableExpression>(var);
         }
     }

+ 18 - 9
src/CodeGeneration.cpp

@@ -84,8 +84,10 @@ std::unique_ptr<llvm::Module> generateModule(const sem::GlobalScope& objects)
             Function* f = fg.generate();
             logger.debug() << "verifying function: " << method->name << std::endl;
             bool corrupt = llvm::verifyFunction(*f, &verifyStream);
-            if (corrupt)
+            if (corrupt) {
+                module->print(verifyStream, nullptr);
                 throw "corrupt llvm function";
+            }
 #ifdef DEBUGGING
             printf("verified function: %s\n", method->name.c_str());
 #endif
@@ -99,8 +101,10 @@ std::unique_ptr<llvm::Module> generateModule(const sem::GlobalScope& objects)
         Function* f = fg.generate();
         logger.debug() << "verifying function: " << method->name << std::endl;
         bool corrupt = llvm::verifyFunction(*f, &verifyStream);
-        if (corrupt)
+        if (corrupt) {
+            module->print(verifyStream, nullptr);
             throw "corrupt llvm function";
+        }
 #ifdef DEBUGGING
         printf("verified function: %s\n", method->name.c_str());
 #endif
@@ -142,19 +146,24 @@ llvm::Function* generateFunction(llvm::Module* module, sem::Method* method)
         throw "invalid return type";
     Function* func = Function::Create(funcType, Function::ExternalLinkage, method->name, module);
     method->llvmNode = func;
-    size_t index = 0;
     
+    // linking alloca instances for funcs
+    auto argIterator = func->arg_begin();
     if (method->thisExpression != nullptr) {
-        method->thisExpression->allocaInst = &*func->args().begin();
-        index++;
+        method->thisExpression->allocaInst = &*argIterator;
+        Logger::getInstance().debug() << "allocaInst of this";
+        argIterator++;
     }
     
-    for (auto arg = func->args().begin() + index; arg != func->args().end(); arg++) {
-        method->arguments[index]->allocaInst = &*arg;
+    size_t argIndex = 0;
+    for (; argIterator != func->arg_end(); argIterator++) {
+        if (argIndex > method->arguments.size())
+            throw "internal error";
+        method->arguments[argIndex]->allocaInst = &*argIterator;
 #ifdef DEBUGGING
-        printf("allocaInst of arg '%s': %p\n", method->arguments[index]->name.c_str(), method->arguments[index]->allocaInst);
+        printf("allocaInst of arg '%s': %p\n", method->arguments[argIndex]->name.c_str(), method->arguments[argIndex]->allocaInst);
 #endif 
-        index++;
+        argIndex++;
     }
     
     //printf("UEEEEEEEE %s\n", method->name.c_str());

+ 4 - 1
src/CodeGeneration.h

@@ -32,9 +32,12 @@ public:
 
     StatementVisitor statementVisitor;
     ExpressionCodegenVisitor expressionVisitor;
+    LValueVisitor lvalueVisitor;
 
     inline FunctionGenerator(const sem::Method& m, llvm::Module* module) :
-        method{ m }, module{ module }
+        method{ m },
+        module{ module },
+        expressionVisitor{ *this }
     {
     }
 

+ 112 - 7
src/CodegenVisitor.cpp

@@ -135,8 +135,14 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::MethodCallExpression& call, ll
     std::vector<Value*> arguments;
     
     if (call.target != nullptr) {
-        auto* target = call.target->accept(*this, builder);
-        arguments.push_back(target);
+        auto* target = call.target->accept(fg.lvalueVisitor, builder);
+        
+        Logger::getInstance().debug() << "creating 'this' argument";
+        if (llvm::LoadInst* li = llvm::dyn_cast<llvm::LoadInst>(target); li) {
+            llvm::Value* ptr = builder.CreateLoad(call.target->type->getLlvmType(builder.getContext())->getPointerTo(), li, "ptrload");
+            arguments.push_back(ptr);
+        } else
+            arguments.push_back(target);
     }
     
     for (size_t i = 0; i < call.arguments.size(); i++) {
@@ -150,9 +156,8 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::MethodCallExpression& call, ll
         
         arguments.push_back(value);
     }
-    auto returnType = call.callee->returnType;
+    //auto returnType = call.callee->returnType;
     llvm::CallInst* callInst = builder.CreateCall(call.callee->llvmNode, arguments);
-    
     return callInst;
 }
 
@@ -160,8 +165,31 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::MethodCallExpression& call, ll
 llvm::Value* ExpressionCodegenVisitor::visit(sem::FieldAccessExpression& access, llvm::IRBuilder<>& builder)
 {
     using llvm::Value;
+    using llvm::Type;
+    
+    Type* type = access.target->type->getLlvmType(builder.getContext());
+    
+    if (type == nullptr)
+        throw "no access type";
+    if (type->isPointerTy()) {
+        type = type->getPointerElementType();
+    }
+    
+    llvm::Value* target = access.target->accept(fg.lvalueVisitor, builder);
+    
+    llvm::ArrayRef<Value*> indexList = {
+        llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, 0, false)),
+        llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, 0, false))
+    };
+    Value* ptr = builder.CreateGEP(type, target, indexList);
+    return builder.CreateLoad(ptr);
     
-    builder.CreateStructGEP(access.type->getLlvmType(builder.getContext()), llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, 0, false)), 0);
+    
+    //builder.CreateStructGEP(type,
+    //                               llvm::ConstantInt::get(builder.getContext(),
+    //                               llvm::APInt(32, 0, false)), 0);
+    return llvm::ConstantInt::get(builder.getContext(),
+                                   llvm::APInt(32, 0, false));
 }
 
 
@@ -178,6 +206,76 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::ThisExpression& thisExpr, llvm
 }
 
 
+llvm::Value* LValueVisitor::visit(sem::Expression& e, llvm::IRBuilder<>& builder)
+{
+    throw "cannot construct lvalue from expression";
+}
+
+
+llvm::Value* LValueVisitor::visit(sem::LocalVariableExpression& lve, llvm::IRBuilder<>& builder)
+{
+    assert(lve.var->allocaInst != nullptr);
+    
+    if (llvm::dyn_cast<llvm::AllocaInst>(lve.var->allocaInst)) {
+        return lve.var->allocaInst;
+        
+        /*llvm::Value* val = builder.CreateLoad(
+            lve.type->getLlvmType(builder.getContext())->getPointerTo(),
+            lve.var->allocaInst
+        );
+        return val;*/
+    }
+    else if (llvm::dyn_cast<llvm::PointerType> (lve.var->allocaInst->getType())) {
+        return lve.var->allocaInst;
+    }
+    else {
+        throw "unable to find alloca instance of local variable";
+    }
+}
+
+
+llvm::Value* LValueVisitor::visit(sem::FieldAccessExpression& access, llvm::IRBuilder<>& builder)
+{
+    /*
+    using llvm::Value;
+    using llvm::Type;
+    
+    auto& fieldType = fae.accessed->type;
+    Type* ptr = fieldType->getLlvmType(builder.getContext())->getPointerTo();
+    
+    llvm::Value* allocaInst = fae.target->accept(*this, builder);
+    
+    if (ptr == nullptr)
+        throw "no access type";
+    
+    llvm::ArrayRef<Value*> indices = {
+        llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, 0, false)),
+        llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, 0, false))
+    };
+    */
+    
+    using llvm::Value;
+    using llvm::Type;
+    
+    Type* type = access.target->type->getLlvmType(builder.getContext());
+    
+    if (type == nullptr)
+        throw "no access type";
+    if (type->isPointerTy()) {
+        type = type->getPointerElementType();
+    }
+    
+    llvm::Value* target = access.target->accept(*this, builder);
+    
+    llvm::ArrayRef<Value*> indexList = {
+        llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, 0, false)),
+        llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, 0, false))
+    };
+    Value* ptr = builder.CreateGEP(type, target, indexList);
+    return ptr;
+}
+
+
 llvm::Value* StatementVisitor::visit(sem::DoEndBlock& assignment,
         qlow::gen::FunctionGenerator& fg)
 {
@@ -266,7 +364,12 @@ llvm::Value* StatementVisitor::visit(sem::AssignmentStatement& assignment,
     Logger& logger = Logger::getInstance();
     llvm::IRBuilder<> builder(fg.getContext());
     builder.SetInsertPoint(fg.getCurrentBlock());
+    
     auto val = assignment.value->accept(fg.expressionVisitor, builder);
+    auto target = assignment.target->accept(fg.lvalueVisitor, builder);
+    
+    return builder.CreateStore(val, target);
+    
     if (auto* targetVar =
         dynamic_cast<sem::LocalVariableExpression*>(assignment.target.get()); targetVar) {
         logger.debug() << "assigning to LocalVariableExpression" << std::endl;
@@ -278,7 +381,10 @@ llvm::Value* StatementVisitor::visit(sem::AssignmentStatement& assignment,
         logger.debug() << "assigning to FieldAccessExpression" << std::endl;
         if (targetVar->target) {
             llvm::Value* target = targetVar->target->accept(fg.expressionVisitor, builder);
-            auto elementPtr = builder.CreateGEP(target, llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, 0)));
+            
+            //auto elementPtr = builder.CreateGEP(targetVar->target->type->getLlvmType(fg.getContext()), target, llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, 0)));
+            auto elementPtr = llvm::ConstantPointerNull::get(val->getType()->getPointerTo());
+            
             builder.CreateStore(val, elementPtr);
         }
         else {
@@ -286,7 +392,6 @@ llvm::Value* StatementVisitor::visit(sem::AssignmentStatement& assignment,
         }
     }
     else {
-        
         logger.debug() << "assigning to instance of " << assignment.target->toString() << std::endl;
         throw "only local variables are assignable at the moment";
     }

+ 27 - 0
src/CodegenVisitor.h

@@ -26,6 +26,7 @@ namespace qlow
 namespace qlow
 {
     class ExpressionCodegenVisitor;
+    class LValueVisitor;
     class StatementVisitor;
 }
 
@@ -47,6 +48,12 @@ class qlow::ExpressionCodegenVisitor :
     >
 {
 public:
+    gen::FunctionGenerator& fg;
+    inline ExpressionCodegenVisitor(gen::FunctionGenerator& fg) :
+        fg{ fg }
+    {
+    }
+    
     llvm::Value* visit(sem::LocalVariableExpression& node, llvm::IRBuilder<>&) override;
     llvm::Value* visit(sem::UnaryOperation& node, llvm::IRBuilder<>&) override;
     llvm::Value* visit(sem::BinaryOperation& node, llvm::IRBuilder<>&) override;
@@ -59,6 +66,23 @@ public:
 };
 
 
+class qlow::LValueVisitor :
+    public Visitor<
+        llvm::Value*,
+        llvm::IRBuilder<>,
+
+        sem::Expression,
+        sem::LocalVariableExpression,
+        sem::FieldAccessExpression
+    >
+{
+public:
+    llvm::Value* visit(sem::Expression& node, llvm::IRBuilder<>&) override;
+    llvm::Value* visit(sem::LocalVariableExpression& node, llvm::IRBuilder<>&) override;
+    llvm::Value* visit(sem::FieldAccessExpression& node, llvm::IRBuilder<>&) override;
+};
+
+
 class qlow::StatementVisitor :
     public Visitor<
         llvm::Value*,
@@ -81,6 +105,9 @@ public:
     llvm::Value* visit(sem::FeatureCallStatement& node, gen::FunctionGenerator&) override;
 };
 
+
+
+
 #endif // QLOW_CODEGEN_VISITOR_H
 
 

+ 2 - 0
src/Scope.cpp

@@ -203,9 +203,11 @@ sem::SymbolTable<sem::Variable>& sem::LocalScope::getLocals(void)
 
 sem::Variable* sem::LocalScope::getVariable(const std::string& name)
 {
+    /*
     if (name == "this") {
         return enclosingMethod->thisExpression.get();
     }
+    */
     
     auto m = localVariables.find(name);
     if (m != localVariables.end())

+ 24 - 3
src/Semantic.cpp

@@ -7,6 +7,8 @@
 
 #include "Util.h"
 
+#include <memory>
+
 using namespace qlow::sem;
 
 namespace qlow
@@ -87,13 +89,17 @@ std::unique_ptr<GlobalScope>
     
     for (auto& [name, semClass] : globalScope->classes) {
         for (auto& [name, method] : semClass->methods) {
-            if (method->astNode->body) // if not declaration
+            if (method->astNode->body) { // if not declaration
+                method->containingType = semClass.get();
+                method->generateThisExpression();
                 method->body = unique_dynamic_cast<sem::DoEndBlock>(method->astNode->body->accept(av, method->scope));
+            }
         }
     }
     for (auto& [name, method] : globalScope->functions) {
-        if (method->astNode->body) // if not declaration
+        if (method->astNode->body) { // if not declaration
             method->body = unique_dynamic_cast<sem::DoEndBlock>(method->astNode->body->accept(av, method->scope));
+        }
     }
     
 #ifdef DEBUGGING
@@ -155,6 +161,14 @@ std::string Field::toString(void) const
 }
 
 
+void Method::generateThisExpression(void)
+{
+    auto te = std::make_unique<ThisExpression>(this);
+    thisExpression = te.get();
+    scope.putVariable(this->thisExpression->name, std::move(te));
+}
+
+
 std::string Method::toString(void) const
 {
     return "Method[" + this->name + "]";
@@ -179,6 +193,10 @@ ACCEPT_DEFINITION(FieldAccessExpression, ExpressionCodegenVisitor, llvm::Value*,
 ACCEPT_DEFINITION(IntConst, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
 ACCEPT_DEFINITION(ThisExpression, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
 
+ACCEPT_DEFINITION(Expression, LValueVisitor, llvm::Value*, llvm::IRBuilder<>&)
+ACCEPT_DEFINITION(LocalVariableExpression, LValueVisitor, llvm::Value*, llvm::IRBuilder<>&)
+ACCEPT_DEFINITION(FieldAccessExpression, LValueVisitor, llvm::Value*, llvm::IRBuilder<>&)
+
 ACCEPT_DEFINITION(AssignmentStatement, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&) 
 ACCEPT_DEFINITION(DoEndBlock, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&) 
 ACCEPT_DEFINITION(IfElseBlock, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&) 
@@ -234,7 +252,10 @@ std::string NewArrayExpression::toString(void) const
 
 std::string MethodCallExpression::toString(void) const
 {
-    return "FeatureCallExpression[" + callee->toString() + "]";
+    if (this->target)
+        return "MethodCallExpression[" + target->toString() + "." + callee->toString() + "]";
+    else
+        return "MethodCallExpression[" + callee->toString() + "]";
 }
 
 

+ 25 - 8
src/Semantic.h

@@ -57,6 +57,7 @@ namespace qlow
     }
 
     class ExpressionCodegenVisitor;
+    class LValueVisitor;
     class StatementVisitor;
 
     namespace gen
@@ -101,6 +102,7 @@ struct qlow::sem::Variable : public SemanticObject
 {
     std::shared_ptr<Type> type;
     std::string name;
+    bool isParameter;
 
     /// if this is a local variable, this stores a reference to the llvm
     /// instance of this variable. If it is a parameter, the parameter value
@@ -108,7 +110,11 @@ struct qlow::sem::Variable : public SemanticObject
     
     Variable(void) = default;
     inline Variable(std::shared_ptr<Type> type, const std::string& name) :
-        type{ std::move(type) }, name{ name }, allocaInst { nullptr } {}
+        type{ std::move(type) },
+        name{ name },
+        allocaInst { nullptr }
+    {
+    }
         
     virtual std::string toString(void) const override;
 };
@@ -127,7 +133,7 @@ struct qlow::sem::Method : public SemanticObject
     std::vector<Variable*> arguments;
     std::string name;
     ast::MethodDefinition* astNode;
-    std::unique_ptr<ThisExpression> thisExpression;
+    ThisExpression* thisExpression;
     std::unique_ptr<DoEndBlock> body;
 
     LocalScope scope;
@@ -138,7 +144,7 @@ struct qlow::sem::Method : public SemanticObject
         containingType{ nullptr },
         returnType{ std::move(returnType) },
         scope{ parentScope, this },
-        thisExpression{ std::make_unique<ThisExpression>(this) },
+        thisExpression{ nullptr },
         body{ nullptr }
     {
     }
@@ -148,11 +154,13 @@ struct qlow::sem::Method : public SemanticObject
         astNode{ astNode },
         name{ astNode->name },
         scope{ parentScope, this },
-        thisExpression{ std::make_unique<ThisExpression>(this) },
+        thisExpression{ nullptr },
         body{ nullptr }
     {
     }
     
+    void generateThisExpression(void);
+    
     virtual std::string toString(void) const override;
 };
 
@@ -161,8 +169,8 @@ struct qlow::sem::ThisExpression : public Variable
 {
     Method* method;
     inline ThisExpression(Method* method) :
-        Variable{ method->returnType, "this" },
-        method{ method}
+        Variable{ std::make_shared<PointerType>(std::make_shared<ClassType>(method->containingType)), "this" },
+        method{ method }
     {
     }
     
@@ -244,7 +252,10 @@ struct qlow::sem::Expression :
     public SemanticObject,
     public Visitable<llvm::Value*,
                      llvm::IRBuilder<>,
-                     qlow::ExpressionCodegenVisitor>
+                     qlow::ExpressionCodegenVisitor>,
+    public Visitable<llvm::Value*,
+                     llvm::IRBuilder<>,
+                     qlow::LValueVisitor>
 {
     std::shared_ptr<sem::Type> type;
     
@@ -252,6 +263,9 @@ struct qlow::sem::Expression :
         type{ std::move(type) }
     {
     }
+    
+    virtual llvm::Value* accept(ExpressionCodegenVisitor& visitor, llvm::IRBuilder<>& arg2) override = 0;
+    virtual llvm::Value* accept(LValueVisitor& visitor, llvm::IRBuilder<>& arg2) override;
 };
 
 
@@ -277,6 +291,7 @@ struct qlow::sem::LocalVariableExpression : public Expression
     }
 
     virtual llvm::Value* accept(ExpressionCodegenVisitor& visitor, llvm::IRBuilder<>& arg2) override;
+    virtual llvm::Value* accept(LValueVisitor& visitor, llvm::IRBuilder<>& arg2);
     virtual std::string toString(void) const override;
 };
 
@@ -365,6 +380,7 @@ struct qlow::sem::MethodCallExpression : public Expression
     inline MethodCallExpression(std::unique_ptr<Expression> target,
                                  Method* callee) :
         Expression{ callee->returnType },
+        target{ std::move(target) },
         callee{ callee }
     {
     }
@@ -379,7 +395,7 @@ struct qlow::sem::FieldAccessExpression : public Expression
 {
     sem::Field* accessed;
     std::unique_ptr<Expression> target;
-    OwningList<Expression> arguments;
+    //OwningList<Expression> arguments;
     
     inline FieldAccessExpression(std::unique_ptr<Expression> target,
                                  Field* accessed ) :
@@ -390,6 +406,7 @@ struct qlow::sem::FieldAccessExpression : public Expression
     }
     
     virtual llvm::Value* accept(ExpressionCodegenVisitor& visitor, llvm::IRBuilder<>& arg2) override;
+    virtual llvm::Value* accept(LValueVisitor& visitor, llvm::IRBuilder<>& arg2) override;
     
     virtual std::string toString(void) const override;
 };

+ 28 - 0
src/Type.cpp

@@ -29,6 +29,34 @@ std::shared_ptr<sem::Type> sem::Type::BOOLEAN =
     std::make_shared<sem::NativeType>(sem::NativeType::Type::BOOLEAN);
 */
 
+std::string sem::PointerType::asString(void) const
+{
+    return derefType->asString() + "*";
+}
+
+
+sem::Scope& sem::PointerType::getScope(void)
+{
+    return scope;
+}
+
+
+llvm::Type* sem::PointerType::getLlvmType(llvm::LLVMContext& context) const
+{
+    return derefType->getLlvmType(context)->getPointerTo();
+}
+
+
+bool sem::PointerType::equals(const Type& other) const
+{
+    if (const PointerType* opt = dynamic_cast<const PointerType*>(&other); opt) {
+        return derefType->equals(*opt->getDerefType());
+    }
+    else
+        return false;
+}
+
+
 std::string sem::ClassType::asString(void) const
 {
     return classType->name;

+ 36 - 9
src/Type.h

@@ -29,6 +29,7 @@ namespace qlow
         
         class Type;
         
+        class PointerType;
         class ClassType;
         class ArrayType;
         class NativeType;
@@ -52,9 +53,17 @@ class qlow::sem::Type : public SemanticObject
 public:
     virtual ~Type(void);
 
-    virtual bool isClassType(void) const = 0;
-    virtual bool isNativeType(void) const = 0;
-    virtual bool isArrayType(void) const = 0;
+    /// \returns false by default
+    virtual inline bool isPointerType(void) const { return false; }
+    
+    /// \returns false by default
+    virtual inline bool isClassType(void) const { return false; }
+    
+    /// \returns false by default
+    virtual inline bool isNativeType(void) const { return false; }
+    
+    /// \returns false by default
+    virtual inline bool isArrayType(void) const { return false; }
 
     virtual std::string asString(void) const = 0;
     virtual Scope& getScope(void) = 0;
@@ -69,6 +78,30 @@ public:
 };
 
 
+class qlow::sem::PointerType : public Type
+{
+    std::shared_ptr<Type> derefType;
+    sem::TypeScope scope;
+public:
+    inline PointerType(std::shared_ptr<Type> derefType) :
+        derefType{ derefType },
+        scope{ *this }
+    {
+    }
+    
+    const std::shared_ptr<Type>& getDerefType(void) const { return derefType; }
+    
+    inline bool isPointerType(void) const override { return true; }
+    
+    virtual std::string asString(void) const override;
+    virtual Scope& getScope(void) override;
+    
+    virtual llvm::Type* getLlvmType(llvm::LLVMContext& context) const override;
+    
+    virtual bool equals(const Type& other) const override;
+};
+
+
 class qlow::sem::ClassType : public Type
 {
     sem::Class* classType;
@@ -81,8 +114,6 @@ public:
     }
     
     inline bool isClassType(void) const override { return true; }
-    inline bool isNativeType(void) const override { return false; }
-    inline bool isArrayType(void) const override { return false; }
     
     std::string asString(void) const;
     Scope& getScope(void);
@@ -105,8 +136,6 @@ public:
     {
     }
     
-    inline bool isClassType(void) const override { return false; }
-    inline bool isNativeType(void) const override { return false; }
     inline bool isArrayType(void) const override { return true; }
     
     std::string asString(void) const;
@@ -143,9 +172,7 @@ public:
     {
     }
     
-    inline bool isClassType(void) const override { return false; }
     inline bool isNativeType(void) const override { return true; }
-    inline bool isArrayType(void) const override { return false; }
     
     std::string asString(void) const;
     Scope& getScope(void);

+ 3 - 3
src/makefile

@@ -1,12 +1,12 @@
 # building depends on debian packages: "g++" "llvm-dev" "bison" "flex" (and "make", duh)
 # running depends on "llvm" if not statically linked
 
-CXX := g++
+CXX := clang++
 
-LLVMCONFIG := llvm-config
+LLVMCONFIG := llvm-config-5.0
 
 INCLUDEDIRS := -I $(shell $(LLVMCONFIG) --includedir)
-CXXFLAGS := -std=c++17 $(INCLUDEDIRS) # -Wall -Wextra
+CXXFLAGS := -std=c++17 $(INCLUDEDIRS) -w # -Wall -Wextra
 
 ifdef STATIC
 LDFLAGS := $(shell $(LLVMCONFIG) --link-static --ldflags --system-libs --libs all) -static -dead-strip -s

+ 6 - 4
src/tests/structs.qlw

@@ -6,8 +6,8 @@ class Vec
 
     yuhu: Integer do
         //x := 123
-        //return x
-        return 123
+        return x
+        //return 123
     end
 end
 
@@ -15,9 +15,11 @@ end
 main: Integer do
     var: Vec
     value: Integer
-    value := 5
+    value := 2
 
-    var.x := 2
+    var.x := value + 10
+
+    //var.x := 2
     value := var.yuhu
 //    var.x := 4
 //    var.hohoo := 4