فهرست منبع

rewritten types

Nicolas Winkler 6 سال پیش
والد
کامیت
6ba72a2fe3
25فایلهای تغییر یافته به همراه431 افزوده شده و 792 حذف شده
  1. 2 2
      src/Builtin.cpp
  2. 11 9
      src/Builtin.h
  3. 139 135
      src/CMakeLists.txt
  4. 6 5
      src/Cast.h
  5. 0 336
      src/CodeGeneration.cpp
  6. 0 57
      src/CodeGeneration.h
  7. 17 15
      src/CodegenVisitor.cpp
  8. 1 1
      src/Driver.cpp
  9. 3 2
      src/Driver.h
  10. 41 32
      src/Scope.cpp
  11. 25 8
      src/Scope.h
  12. 34 24
      src/ast/AstVisitor.cpp
  13. 1 0
      src/ast/Parser.cpp
  14. 16 21
      src/ast/lexer.l
  15. 7 1
      src/ast/syntax.y
  16. 1 0
      src/main.cpp
  17. 2 2
      src/makefile
  18. 27 19
      src/sem/CodeGeneration.cpp
  19. 3 3
      src/sem/Context.cpp
  20. 3 3
      src/sem/Context.h
  21. 9 7
      src/sem/Semantic.cpp
  22. 20 15
      src/sem/Semantic.h
  23. 43 8
      src/sem/Type.cpp
  24. 20 1
      src/sem/Type.h
  25. 0 86
      src/tests/VisitorTest.cpp

+ 2 - 2
src/Builtin.cpp

@@ -5,13 +5,13 @@
 using namespace qlow;
 
 
-sem::NativeScope qlow::sem::generateNativeScope(void)
+sem::NativeScope qlow::sem::generateNativeScope(Context& context)
 {
     using sem::Class;
     using sem::NativeType;
     using sem::NativeScope;
     
-    NativeScope scope;
+    NativeScope scope{ context };
     
     /*std::map<std::string, NativeType::Type> natives = {
         { "Boolean",    NativeType::BOOLEAN },

+ 11 - 9
src/Builtin.h

@@ -12,7 +12,7 @@ namespace qlow
 {
     namespace sem
     {
-        NativeScope generateNativeScope(void);
+        NativeScope generateNativeScope(Context& context);
         
         struct NativeMethod;
         struct UnaryNativeMethod;
@@ -23,7 +23,7 @@ namespace qlow
 
 struct qlow::sem::NativeMethod : public sem::Method
 {
-    inline NativeMethod(TypeId returnType) :
+    inline NativeMethod(Context& context, TypeId returnType) :
         Method{ NativeScope::getInstance(), returnType }
     {
     }
@@ -37,10 +37,11 @@ struct qlow::sem::UnaryNativeMethod : public sem::NativeMethod
 {
     std::function<llvm::Value*(llvm::IRBuilder<>&, llvm::Value*)> generator;
     
-    inline UnaryNativeMethod(TypeId returnType,
-        const std::function
-        <llvm::Value*(llvm::IRBuilder<>&, llvm::Value*)>& generator) :
-        NativeMethod{ returnType },
+    inline UnaryNativeMethod(Context& context,
+                             TypeId returnType,
+                             const std::function
+                             <llvm::Value*(llvm::IRBuilder<>&, llvm::Value*)>& generator) :
+        NativeMethod{ context, returnType },
         generator{ generator }
     {
     }
@@ -58,13 +59,14 @@ struct qlow::sem::BinaryNativeMethod : public sem::NativeMethod
     Func generator;
     Variable argument;
     
-    inline BinaryNativeMethod(TypeId returnType,
+    inline BinaryNativeMethod(Context& context,
+                              TypeId returnType,
                               TypeId argumentType,
         
         Func&& generator) :
-        NativeMethod{ returnType },
+        NativeMethod{ context, returnType },
         generator{ generator },
-        argument{ argumentType, "arg" }
+        argument{ context, argumentType, "arg" }
     {
         Method::arguments = { &argument };
     }

+ 139 - 135
src/CMakeLists.txt

@@ -10,6 +10,8 @@ check_ipo_supported(RESULT ipo_supported)
 set(CMAKE_CXX_STANDARD 17)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
 
+set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra -g")
+
 find_package(BISON)
 find_package(FLEX)
 find_package(LLVM REQUIRED CONFIG)
@@ -40,141 +42,143 @@ endif()
 
 
 #explicit_llvm_config(${PROJECT_NAME} STATIC_LIBRARY)
-llvm_config(${PROJECT_NAME}
-    MIRParser
-    LTO
-    Passes
-    ObjCARCOpts
-    LibDriver
-    MCJIT
-    XCoreDisassembler
-    XCoreCodeGen
-    XCoreDesc
-    XCoreInfo
-    XCoreAsmPrinter
-    X86Disassembler
-    X86AsmParser
-    SystemZDisassembler
-    SystemZCodeGen
-    SystemZAsmParser
-    SystemZDesc
-    SystemZInfo
-    SystemZAsmPrinter
-    SparcDisassembler
-    SparcCodeGen
-    SparcAsmParser
-    SparcDesc
-    SparcInfo
-    SparcAsmPrinter
-    PowerPCDisassembler
-    PowerPCCodeGen
-    PowerPCAsmParser
-    PowerPCDesc
-    PowerPCInfo
-    PowerPCAsmPrinter
-    NVPTXCodeGen
-    NVPTXDesc
-    NVPTXInfo
-    NVPTXAsmPrinter
-    MSP430CodeGen
-    MSP430Desc
-    MSP430Info
-    MSP430AsmPrinter
-    MipsDisassembler
-    MipsCodeGen
-    MipsAsmParser
-    MipsDesc
-    MipsInfo
-    MipsAsmPrinter
-    LanaiDisassembler
-    LanaiCodeGen
-    LanaiAsmParser
-    LanaiDesc
-    LanaiAsmPrinter
-    LanaiInfo
-    HexagonDisassembler
-    HexagonCodeGen
-    HexagonAsmParser
-    HexagonDesc
-    HexagonInfo
-    BPFDisassembler
-    BPFCodeGen
-    BPFAsmParser
-    BPFDesc
-    BPFInfo
-    BPFAsmPrinter
-    ARMDisassembler
-    ARMCodeGen
-    ARMAsmParser
-    ARMDesc
-    ARMInfo
-    ARMAsmPrinter
-    ARMUtils
-    AMDGPUDisassembler
-    AMDGPUCodeGen
-    AMDGPUAsmParser
-    AMDGPUDesc
-    AMDGPUInfo
-    AMDGPUAsmPrinter
-    AMDGPUUtils
-    AArch64Disassembler
-    AArch64CodeGen
-    AArch64AsmParser
-    AArch64Desc
-    AArch64Info
-    AArch64AsmPrinter
-    AArch64Utils
-    Interpreter
-    WindowsManifest
-    Symbolize
-    DebugInfoPDB
-    DebugInfoDWARF
-    LineEditor
-    X86CodeGen
-    GlobalISel
-    X86Desc
-    X86Info
-    MCDisassembler
-    X86AsmPrinter
-    X86Utils
-    SelectionDAG
-    AsmPrinter
-    CodeGen
-    FuzzMutate
-    DlltoolDriver
-    Option
-    Coroutines
-    ipo
-    Instrumentation
-    Vectorize
-    ScalarOpts
-    Linker
-    IRReader
-    AsmParser
-    InstCombine
-    BitWriter
-    AggressiveInstCombine
-    Coverage
-    ObjectYAML
-    OrcJIT
-    TransformUtils
-    ExecutionEngine
-    Target
-    Analysis
-    ProfileData
-    RuntimeDyld
-    Object
-    MCParser
-    BitReader
-    MC
-    DebugInfoCodeView
-    DebugInfoMSF
-    Core
-    BinaryFormat
-    TableGen
-    Support
-    Demangle
-)
+llvm_config(${PROJECT_NAME})
+target_link_libraries(${PROJECT_NAME} LLVM)
+
+#    MIRParser
+#    LTO
+#    Passes
+#    ObjCARCOpts
+#    LibDriver
+#    MCJIT
+#    XCoreDisassembler
+#    XCoreCodeGen
+#    XCoreDesc
+#    XCoreInfo
+#    XCoreAsmPrinter
+#    X86Disassembler
+#    X86AsmParser
+#    SystemZDisassembler
+#    SystemZCodeGen
+#    SystemZAsmParser
+#    SystemZDesc
+#    SystemZInfo
+#    SystemZAsmPrinter
+#    SparcDisassembler
+#    SparcCodeGen
+#    SparcAsmParser
+#    SparcDesc
+#    SparcInfo
+#    SparcAsmPrinter
+#    PowerPCDisassembler
+#    PowerPCCodeGen
+#    PowerPCAsmParser
+#    PowerPCDesc
+#    PowerPCInfo
+#    PowerPCAsmPrinter
+#    NVPTXCodeGen
+#    NVPTXDesc
+#    NVPTXInfo
+#    NVPTXAsmPrinter
+#    MSP430CodeGen
+#    MSP430Desc
+#    MSP430Info
+#    MSP430AsmPrinter
+#    MipsDisassembler
+#    MipsCodeGen
+#    MipsAsmParser
+#    MipsDesc
+#    MipsInfo
+#    MipsAsmPrinter
+#    LanaiDisassembler
+#    LanaiCodeGen
+#    LanaiAsmParser
+#    LanaiDesc
+#    LanaiAsmPrinter
+#    LanaiInfo
+#    HexagonDisassembler
+#    HexagonCodeGen
+#    HexagonAsmParser
+#    HexagonDesc
+#    HexagonInfo
+#    BPFDisassembler
+#    BPFCodeGen
+#    BPFAsmParser
+#    BPFDesc
+#    BPFInfo
+#    BPFAsmPrinter
+#    ARMDisassembler
+#    ARMCodeGen
+#    ARMAsmParser
+#    ARMDesc
+#    ARMInfo
+#    ARMAsmPrinter
+#    ARMUtils
+#    AMDGPUDisassembler
+#    AMDGPUCodeGen
+#    AMDGPUAsmParser
+#    AMDGPUDesc
+#    AMDGPUInfo
+#    AMDGPUAsmPrinter
+#    AMDGPUUtils
+#    AArch64Disassembler
+#    AArch64CodeGen
+#    AArch64AsmParser
+#    AArch64Desc
+#    AArch64Info
+#    AArch64AsmPrinter
+#    AArch64Utils
+#    Interpreter
+#    WindowsManifest
+#    Symbolize
+#    DebugInfoPDB
+#    DebugInfoDWARF
+#    LineEditor
+#    X86CodeGen
+#    GlobalISel
+#    X86Desc
+#    X86Info
+#    MCDisassembler
+#    X86AsmPrinter
+#    X86Utils
+#    SelectionDAG
+#    AsmPrinter
+#    CodeGen
+#    FuzzMutate
+#    DlltoolDriver
+#    Option
+#    Coroutines
+#    ipo
+#    Instrumentation
+#    Vectorize
+#    ScalarOpts
+#    Linker
+#    IRReader
+#    AsmParser
+#    InstCombine
+#    BitWriter
+#    AggressiveInstCombine
+#    Coverage
+#    ObjectYAML
+#    OrcJIT
+#    TransformUtils
+#    ExecutionEngine
+#    Target
+#    Analysis
+#    ProfileData
+#    RuntimeDyld
+#    Object
+#    MCParser
+#    BitReader
+#    MC
+#    DebugInfoCodeView
+#    DebugInfoMSF
+#    Core
+#    BinaryFormat
+#    TableGen
+#    Support
+#    Demangle
+#)
 
 
 

+ 6 - 5
src/Cast.h

@@ -2,6 +2,7 @@
 #define QLOW_SEM_CAST_H
 
 #include <memory>
+#include "Type.h"
 
 namespace qlow
 {
@@ -18,18 +19,18 @@ namespace qlow
 class qlow::sem::Cast
 {
 public:
-    std::weak_ptr<Type> to;
+    TypeId to;
     
     bool isExplicit;
     
-    inline Cast(std::weak_ptr<Type> to) :
-        to{ std::move(to) },
+    inline Cast(TypeId to) :
+        to{ to },
         isExplicit{ true }
     {
     }
     
-    inline Cast(std::weak_ptr<Type> to, bool isExplicit) :
-        to{ std::move(to) },
+    inline Cast(TypeId to, bool isExplicit) :
+        to{ to },
         isExplicit{ isExplicit }
     {
     }

+ 0 - 336
src/CodeGeneration.cpp

@@ -1,336 +0,0 @@
-#include "CodeGeneration.h"
-
-#include <llvm/IR/LLVMContext.h>
-#include <llvm/IR/LegacyPassManager.h>
-#include <llvm/Transforms/IPO/PassManagerBuilder.h>
-#include <llvm/IR/Type.h>
-#include <llvm/IR/DerivedTypes.h>
-#include <llvm/IR/Constants.h>
-#include <llvm/IR/BasicBlock.h>
-#include <llvm/IR/Verifier.h>
-#include <llvm/IR/IRBuilder.h>
-#include <llvm/IR/Attributes.h>
-#include <llvm/Target/TargetMachine.h>
-#include <llvm/Support/TargetRegistry.h>
-#include <llvm/Support/TargetSelect.h>
-#include <llvm/Support/FileSystem.h>
-#include <llvm/Support/raw_os_ostream.h>
-
-
-using namespace qlow;
-
-static llvm::LLVMContext context;
-
-namespace qlow
-{
-namespace gen
-{
-
-std::unique_ptr<llvm::Module> generateModule(const sem::GlobalScope& objects)
-{
-    using llvm::Module;
-    using llvm::Function;
-    using llvm::Argument;
-    using llvm::Type;
-    using llvm::FunctionType;
-    using llvm::BasicBlock;
-    using llvm::Value;
-    using llvm::IRBuilder;
-    
-    Logger& logger = Logger::getInstance();
-    
-#ifdef DEBUGGING
-        printf("creating llvm module\n"); 
-#endif 
-
-    std::unique_ptr<Module> module = llvm::make_unique<Module>("qlow_module", context);
-
-    // create llvm structs
-    // TODO implement detection of circles
-    for (auto& [name, cl] : objects.classes) {
-        llvm::StructType* st;
-        std::vector<llvm::Type*> fields;
-#ifdef DEBUGGING
-        printf("creating llvm struct for %s\n", name.c_str());
-#endif
-        int llvmStructIndex = 0;
-        for (auto& [name, field] : cl->fields) {
-            field->llvmStructIndex = llvmStructIndex;
-            fields.push_back(field->type->getLlvmType(context));
-            if (fields[fields.size() - 1] == nullptr)
-                throw "internal error: possible circular dependency";
-            
-            llvmStructIndex++;
-        }
-        st = llvm::StructType::create(context, fields, name);
-        cl->llvmType = st;
-    }
-    
-    llvm::AttrBuilder ab;
-    ab.addAttribute(llvm::Attribute::AttrKind::NoInline);
-    ab.addAttribute(llvm::Attribute::AttrKind::NoUnwind);
-    //ab.addAttribute(llvm::Attribute::AttrKind::OptimizeNone);
-    //ab.addAttribute(llvm::Attribute::AttrKind::UWTable);
-    ab.addAttribute("no-frame-pointer-elim", "true");
-    ab.addAttribute("no-frame-pointer-elim-non-leaf");
-    llvm::AttributeSet as = llvm::AttributeSet::get(context, ab);
-    
-    
-    std::vector<llvm::Function*> functions;
-    auto verifyStream = llvm::raw_os_ostream(logger.debug());
-    
-    // create all llvm functions
-    for (auto& [name, cl] : objects.classes) {
-        for (auto& [name, method] : cl->methods) {
-            Function* func = generateFunction(module.get(), method.get());
-            for (auto a : as) {
-                func->addFnAttr(a);
-            }
-            functions.push_back(func);
-        }
-    }
-    
-    for (auto& [name, method] : objects.functions) {
-        Function* func = generateFunction(module.get(), method.get());
-        for (auto a : as) {
-            func->addFnAttr(a);
-        }
-        functions.push_back(func);
-    }
-
-    for (auto& [name, cl] : objects.classes){
-        for (auto& [name, method] : cl->methods) {
-            if (!method->body)
-                continue;
-            
-            FunctionGenerator fg(*method, module.get(), as);
-            Function* f = fg.generate();
-            logger.debug() << "verifying function: " << method->name << std::endl;
-            bool corrupt = llvm::verifyFunction(*f, &verifyStream);
-            if (corrupt) {
-                module->print(verifyStream, nullptr);
-                throw "corrupt llvm function";
-            }
-#ifdef DEBUGGING
-            printf("verified function: %s\n", method->name.c_str());
-#endif
-        }
-    }
-    for (auto& [name, method] : objects.functions) {
-        if (!method->body)
-            continue;
-        
-        FunctionGenerator fg(*method, module.get(), as);
-        Function* f = fg.generate();
-        logger.debug() << "verifying function: " << method->name << std::endl;
-        bool corrupt = llvm::verifyFunction(*f, &verifyStream);
-        if (corrupt) {
-            module->print(verifyStream, nullptr);
-            throw "corrupt llvm function";
-        }
-#ifdef DEBUGGING
-        printf("verified function: %s\n", method->name.c_str());
-#endif
-    }
-    return module;
-}
-
-
-llvm::Function* generateFunction(llvm::Module* module, sem::Method* method)
-{
-    using llvm::Function;
-    using llvm::Argument;
-    using llvm::Type;
-    using llvm::FunctionType;
-    
-    Type* returnType;
-    if (method->returnType)
-        returnType = method->returnType->getLlvmType(context);
-    else
-        returnType = llvm::Type::getVoidTy(context);
-    
-    std::vector<Type*> argumentTypes;
-    if (method->thisExpression != nullptr) {
-        Type* enclosingType = method->thisExpression->type->getLlvmType(context);
-        argumentTypes.push_back(enclosingType);
-    }
-    
-    for (auto& arg : method->arguments) {
-        Type* argumentType = arg->type->getLlvmType(context);
-        argumentTypes.push_back(argumentType);
-    }
-    
-    FunctionType* funcType = FunctionType::get(
-        returnType, argumentTypes, false);
-#ifdef DEBUGGING
-    printf("looking up llvm type of %s\n", method->name.c_str());
-#endif 
-    if (returnType == nullptr)
-        throw "invalid return type";
-    Function* func = Function::Create(funcType, Function::ExternalLinkage, method->name, module);
-    method->llvmNode = func;
-    
-    // linking alloca instances for funcs
-    auto argIterator = func->arg_begin();
-    if (method->thisExpression != nullptr) {
-        method->thisExpression->allocaInst = &*argIterator;
-        Logger::getInstance().debug() << "allocaInst of this";
-        argIterator++;
-    }
-    
-    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[argIndex]->name.c_str(), method->arguments[argIndex]->allocaInst);
-#endif 
-        argIndex++;
-    }
-    
-    //printf("UEEEEEEEE %s\n", method->name.c_str());
-    return func;
-}
-
-
-void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Module> module, int optLevel)
-{
-    using llvm::legacy::PassManager;
-    using llvm::PassManagerBuilder;
-    using llvm::raw_fd_ostream;
-    using llvm::Target;
-    using llvm::TargetMachine;
-    using llvm::TargetRegistry;
-    using llvm::TargetOptions;
-
-    Logger& logger = Logger::getInstance();
-    logger.debug() << "verifying mod" << std::endl;
-    auto ostr = llvm::raw_os_ostream(logger.debug());
-#ifdef DEBUGGING
-    module->print(ostr, nullptr);
-#endif
-    bool broken = llvm::verifyModule(*module);
-    
-    if (broken)
-        throw "invalid llvm module";
-    
-    logger.debug() << "mod verified" << std::endl;
-
-    llvm::InitializeAllTargetInfos();
-    llvm::InitializeAllTargets();
-    llvm::InitializeAllTargetMCs();
-    llvm::InitializeAllAsmParsers();
-    llvm::InitializeAllAsmPrinters();
-
-    PassManager pm;
-    
-    int sizeLevel = 0;
-    PassManagerBuilder builder;
-    builder.OptLevel = optLevel;
-    builder.SizeLevel = sizeLevel;
-    if (optLevel >= 2) {
-        builder.DisableUnitAtATime = false;
-        builder.DisableUnrollLoops = false;
-        builder.LoopVectorize = true;
-        builder.SLPVectorize = true;
-    }
-
-    builder.populateModulePassManager(pm);
-
-    const char cpu[] = "generic";
-    const char features[] = "";
-
-    std::string error;
-    std::string targetTriple = llvm::sys::getDefaultTargetTriple();
-    const Target* target = TargetRegistry::lookupTarget(targetTriple, error);
-
-    if (!target) {
-        logger.debug() << "could not create target: " << error << std::endl;
-        throw "internal error";
-    }
-
-    TargetOptions targetOptions;
-    auto relocModel = llvm::Optional<llvm::Reloc::Model>(llvm::Reloc::Model::PIC_);
-    std::unique_ptr<TargetMachine> targetMachine(
-        target->createTargetMachine(targetTriple, cpu,
-            features, targetOptions, relocModel));
-
-    std::error_code errorCode;
-    raw_fd_ostream dest(filename, errorCode, llvm::sys::fs::F_None);
-    targetMachine->addPassesToEmitFile(pm, dest, &dest,
-//        llvm::LLVMTargetMachine::CGFT_ObjectFile,
-        llvm::TargetMachine::CGFT_ObjectFile);
-
-    pm.run(*module);
-    dest.flush();
-    dest.close();
-
-    return;
-}
-
-} // namespace gen
-} // namespace qlow
-
-
-llvm::Function* qlow::gen::FunctionGenerator::generate(void)
-{
-    using llvm::Function;
-    using llvm::Argument;
-    using llvm::Type;
-    using llvm::FunctionType;
-    using llvm::BasicBlock;
-    using llvm::Value;
-    using llvm::IRBuilder;
-    
-#ifdef DEBUGGING
-    printf("generate function %s\n", method.name.c_str()); 
-#endif
-
-    Function* func = module->getFunction(method.name);
-
-    if (func == nullptr) {
-        throw "internal error: function not found";
-    }
-
-    BasicBlock* bb = BasicBlock::Create(context, "entry", func);
-
-    pushBlock(bb);
-
-    IRBuilder<> builder(context);
-    builder.SetInsertPoint(bb);
-    for (auto& [name, var] : method.body->scope.getLocals()) {
-        if (var.get() == nullptr)
-            throw "wtf null variable";
-        if (var->type == nullptr)
-            throw "wtf null type";
-        
-        llvm::AllocaInst* v = builder.CreateAlloca(var->type->getLlvmType(context));
-        var->allocaInst = v;
-    }
-    
-    for (auto& statement : method.body->statements) {
-#ifdef DEBUGGING
-        printf("statement visit %s\n", statement->toString().c_str());
-#endif
-        statement->accept(statementVisitor, *this);
-    }
-    
-
-#ifdef DEBUGGING
-    printf("End of Function\n");
-#endif
-    
-    //Value* val = llvm::ConstantFP::get(context, llvm::APFloat(5.0));
-    
-    builder.SetInsertPoint(getCurrentBlock());
-    if (method.returnType->equals(sem::NativeType(sem::NativeType::Type::VOID))) {
-        if (!getCurrentBlock()->getTerminator())
-            builder.CreateRetVoid();
-    }
-
-    return func;
-}
-
-
-

+ 0 - 57
src/CodeGeneration.h

@@ -1,57 +0,0 @@
-#ifndef QLOW_CODE_GENERATION_H
-#define QLOW_CODE_GENERATION_H
-
-#include "Semantic.h"
-#include "Builtin.h"
-#include "CodegenVisitor.h"
-
-#include <stack>
-
-#include <llvm/IR/Module.h>
-
-namespace qlow
-{
-namespace gen
-{
-    std::unique_ptr<llvm::Module> generateModule(const sem::GlobalScope& objects);
-    llvm::Function* generateFunction (llvm::Module* module, sem::Method* method);
-    void generateObjectFile(const std::string& name, std::unique_ptr<llvm::Module> module, int optLevel);
-
-    class FunctionGenerator;
-}
-}
-
-class qlow::gen::FunctionGenerator
-{
-    const sem::Method& method;
-    llvm::Module* module;
-    llvm::AttributeSet& attributes;
-
-    std::stack<llvm::BasicBlock*> basicBlocks;
-
-public:
-
-    StatementVisitor statementVisitor;
-    ExpressionCodegenVisitor expressionVisitor;
-    LValueVisitor lvalueVisitor;
-
-    inline FunctionGenerator(const sem::Method& m, llvm::Module* module,
-        llvm::AttributeSet& attributes) :
-        method{ m },
-        module{ module },
-        attributes{ attributes },
-        expressionVisitor{ *this }
-    {
-    }
-
-    llvm::Function* generate(void);
-
-    inline llvm::Module* getModule(void) const { return module; }
-    inline llvm::LLVMContext& getContext(void) const { return module->getContext(); }
-    inline llvm::BasicBlock* getCurrentBlock(void) const { return basicBlocks.top(); }
-    inline void pushBlock(llvm::BasicBlock* bb) { basicBlocks.push(bb); }
-    inline llvm::BasicBlock* popBlock(void) { auto* bb = basicBlocks.top(); basicBlocks.pop(); return bb; }
-};
-
-
-#endif // QLOW_CODE_GENERATION_H

+ 17 - 15
src/CodegenVisitor.cpp

@@ -31,7 +31,7 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::UnaryOperation& unop, llvm::IR
     auto value = unop.arg->accept(*this, builder);
     auto& type = unop.arg->type;
     
-    if (type->equals(sem::NativeType(sem::NativeType::Type::VOID)))
+    if (type == sem::NO_TYPE)//(type->equals(sem::NativeType(sem::NativeType::Type::VOID)))
         throw "invalid type to negate";
 
     /*
@@ -74,12 +74,14 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::BinaryOperation& binop, llvm::
     }
     
     Value* implicitelyCastedRight = right;
-    if (!leftType->equals(*rightType))
-        implicitelyCastedRight = dynamic_cast<sem::NativeType*>(leftType.get())->generateImplicitCast(right);
+    // TODO rewritten types
+    /*if (leftType != rightType))
+        implicitelyCastedRight = dynamic_cast<sem::NativeType*>(leftType.get())->generateImplicitCast(right);*/
     
+    /*
     if (dynamic_cast<sem::NativeType*>(leftType.get())->isIntegerType()) {
         // TODO allow integer operations
-    }
+    }*/
     
    /* 
     // TODO insert type checks
@@ -110,11 +112,11 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::BinaryOperation& binop, llvm::
 
 llvm::Value* ExpressionCodegenVisitor::visit(sem::CastExpression& cast, llvm::IRBuilder<>& builder)
 {
-    return builder.CreateCast(
+    /*return builder.CreateCast(
         llvm::Instruction::CastOps::SExt,
         cast.expression->accept(*this, builder),
-        cast.targetType->getLlvmType(builder.getContext())
-    );
+        context.getType(cast.targetType).value().getLlvmType(builder.getContext())
+    );*/
 }
 
 
@@ -127,7 +129,7 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::NewArrayExpression& naexpr, ll
 
 llvm::Value* ExpressionCodegenVisitor::visit(sem::MethodCallExpression& call, llvm::IRBuilder<>& builder)
 {
-    using llvm::Value;
+    /*using llvm::Value;
     if (call.arguments.size() != call.callee->arguments.size()) {
         throw "wrong number of arguments";
     }
@@ -158,13 +160,13 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::MethodCallExpression& call, ll
     }
     //auto returnType = call.callee->returnType;
     llvm::CallInst* callInst = builder.CreateCall(call.callee->llvmNode, arguments);
-    return callInst;
+    return callInst;*/
 }
 
 
 llvm::Value* ExpressionCodegenVisitor::visit(sem::FieldAccessExpression& access, llvm::IRBuilder<>& builder)
 {
-    using llvm::Value;
+    /*using llvm::Value;
     using llvm::Type;
     
     Type* type = access.target->type->getLlvmType(builder.getContext());
@@ -190,7 +192,7 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::FieldAccessExpression& access,
     //                               llvm::ConstantInt::get(builder.getContext(),
     //                               llvm::APInt(32, 0, false)), 0);
     return llvm::ConstantInt::get(builder.getContext(),
-                                   llvm::APInt(32, 0, false));
+                                   llvm::APInt(32, 0, false));*/
 }
 
 
@@ -273,7 +275,7 @@ llvm::Value* LValueVisitor::visit(sem::FieldAccessExpression& access, llvm::IRBu
     using llvm::Value;
     using llvm::Type;
     
-    Type* type = access.target->type->getLlvmType(builder.getContext());
+    /*Type* type = access.target->type->getLlvmType(builder.getContext());
     
     if (type == nullptr)
         throw "no access type";
@@ -289,7 +291,7 @@ llvm::Value* LValueVisitor::visit(sem::FieldAccessExpression& access, llvm::IRBu
         llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, 0, false))
     };
     Value* ptr = builder.CreateGEP(type, target, indexList);
-    return ptr;
+    return ptr;*/
 }
 
 
@@ -453,9 +455,9 @@ llvm::Value* StatementVisitor::visit(sem::FeatureCallStatement& fc, gen::Functio
 llvm::Value* CastGenerator::generateCast(llvm::Value* toCast,
                                           llvm::IRBuilder<>& b)
 {
-    return b.CreateCast(
+    /*return b.CreateCast(
         llvm::Instruction::CastOps::BitCast, toCast,
-        cast.to->getLlvmType(b.getContext()));
+        cast.to->getLlvmType(b.getContext()));*/
 }
 
 

+ 1 - 1
src/Driver.cpp

@@ -197,7 +197,7 @@ bool Driver::semanticStage(void)
     bool errorOccurred = false;
 
     try {
-        this->semClasses = qlow::sem::createFromAst(*this->ast);
+        std::tie(this->context, this->semClasses) = qlow::sem::createFromAst(*this->ast);
     }
     catch(SemanticError& se) {
         se.print(logger);

+ 3 - 2
src/Driver.h

@@ -39,8 +39,9 @@ struct qlow::Options
 class qlow::Driver
 {
     Options options;
-    std::unique_ptr<qlow::ast::Ast> ast = nullptr;
-    std::unique_ptr<qlow::sem::GlobalScope> semClasses = nullptr;
+    std::unique_ptr<ast::Ast> ast = nullptr;
+    std::unique_ptr<sem::Context> context = nullptr;
+    std::unique_ptr<sem::GlobalScope> semClasses = nullptr;
 public:
     Driver(void) = delete;
     Driver(int argc, char** argv);

+ 41 - 32
src/Scope.cpp

@@ -22,7 +22,7 @@ sem::Method* sem::Scope::resolveMethod(const std::string& name,
         return nullptr;
     
     for (size_t i = 0; i < argumentTypes.size(); i++) {
-        if (!m->arguments[i]->type->equals(*argumentTypes[i]))
+        if (!m->arguments[i]->type == argumentTypes[i])
             return nullptr;
     }
     
@@ -45,14 +45,14 @@ sem::Method* sem::GlobalScope::getMethod(const std::string& name)
 }
 
 
-std::shared_ptr<sem::Type> sem::GlobalScope::getType(const ast::Type& name)
+sem::TypeId sem::GlobalScope::getType(const ast::Type& name)
 {
     if (const auto* arr = dynamic_cast<const ast::ArrayType*>(&name); arr) {
-        return std::make_shared<sem::ArrayType>(getType(*arr->arrayType));
+        return context.getArrayOf(getType(*arr->arrayType));
     }
     
     if (const auto* ptr = dynamic_cast<const ast::PointerType*>(&name)) {
-        return std::make_shared<sem::PointerType>(getType(*ptr->derefType));
+        return context.getPointerTo(getType(*ptr->derefType));
     }
     
     auto native = NativeScope::getInstance().getType(name);
@@ -69,15 +69,15 @@ std::shared_ptr<sem::Type> sem::GlobalScope::getType(const ast::Type& name)
     
     auto t = classes.find(classType->typeName);
     if (t != classes.end())
-        return std::make_shared<sem::ClassType>(t->second.get());
+        return context.addType(Type::createClassType(context, t->second.get()));
     
-    return nullptr;
+    return NO_TYPE;
 }
 
 
-std::shared_ptr<sem::Type> sem::GlobalScope::getReturnableType(void)
+qlow::sem::TypeId sem::GlobalScope::getReturnableType(void)
 {
-    return nullptr;
+    return NO_TYPE;
 }
 
 
@@ -93,27 +93,29 @@ std::string sem::GlobalScope::toString(void)
 }
 
 
-std::shared_ptr<sem::Type> sem::NativeScope::getType(const ast::Type& name)
+sem::TypeId sem::NativeScope::getType(const ast::Type& name)
 {
     if (const auto* arr = dynamic_cast<const ast::ArrayType*>(&name); arr) {
-        return std::make_shared<sem::ArrayType>(getType(*arr->arrayType));
+        return context.getArrayOf(getType(*arr->arrayType));
     }
     
     const auto* classType = dynamic_cast<const ast::ClassType*>(&name);
    
     if (!classType)
-        return std::make_shared<sem::NativeType>(NativeType::VOID);
+        return NO_TYPE;
     
     
     auto t = types.find(classType->typeName);
     if (t != types.end())
-        return *t->second;
+        return t->second;
     
-    return nullptr;
+    return NO_TYPE;
 }
 
 
-sem::NativeScope sem::NativeScope::instance = sem::generateNativeScope();
+// TODO rewrite
+static sem::Context c;
+sem::NativeScope sem::NativeScope::instance = sem::generateNativeScope(c);
 sem::NativeScope& sem::NativeScope::getInstance(void)
 {
     return instance;
@@ -174,11 +176,12 @@ sem::TypeId sem::ClassScope::getType(const ast::Type& name)
 
 sem::TypeId sem::ClassScope::getReturnableType(void)
 {
-    return nullptr;
+    return NO_TYPE;
 }
 
 
 sem::LocalScope::LocalScope(Scope& parentScope, Method* enclosingMethod) :
+    Scope{ parentScope.getContext() },
     parentScope{ parentScope },
     returnType{ enclosingMethod->returnType },
     enclosingMethod{ enclosingMethod }
@@ -186,6 +189,7 @@ sem::LocalScope::LocalScope(Scope& parentScope, Method* enclosingMethod) :
 }
 
 sem::LocalScope::LocalScope(LocalScope& parentScope) :
+    Scope{ parentScope.getContext() },
     parentScope{ parentScope },
     returnType{ parentScope.returnType },
     enclosingMethod{ parentScope.enclosingMethod }
@@ -227,13 +231,13 @@ sem::Method* sem::LocalScope::getMethod(const std::string& name)
 }
 
 
-std::shared_ptr<sem::Type> sem::LocalScope::getType(const ast::Type& name)
+sem::TypeId sem::LocalScope::getType(const ast::Type& name)
 {
     return parentScope.getType(name);
 }
 
 
-std::shared_ptr<sem::Type> sem::LocalScope::getReturnableType(void)
+sem::TypeId sem::LocalScope::getReturnableType(void)
 {
     return returnType;
 }
@@ -253,36 +257,41 @@ std::string sem::LocalScope::toString(void)
 
 sem::Variable* sem::TypeScope::getVariable(const std::string& name)
 {
-    if (ClassType* ct = dynamic_cast<ClassType*>(&type); ct) {
-        auto& fields = ct->getClassType()->fields;
-        if (fields.find(name) != fields.end())
-            return fields[name].get();
+    if (auto ty = context.getType(type)) {
+        if (ty.value().get().getKind() == Type::Kind::CLASS) {
+            auto& fields = ty.value().get().getClass()->fields;
+            if (fields.find(name) != fields.end())
+                return fields[name].get();
+        }
     }
     return nullptr;
-    return nullptr;
 }
 
 
+
 sem::Method* sem::TypeScope::getMethod(const std::string& name)
 {
-    if (ClassType* ct = dynamic_cast<ClassType*>(&type); ct) {
-        auto& methods = ct->getClassType()->methods;
-        if (methods.find(name) != methods.end())
-            return methods[name].get();
+    if (auto ty = context.getType(type)) {
+        if (ty.value().get().getKind() == Type::Kind::CLASS) {
+            auto classRef = ty.value().get().getClass();
+            auto& methods = classRef->methods;
+            if (methods.find(name) != methods.end())
+                return methods[name].get();
+        }
     }
     return nullptr;
 }
 
 
-std::shared_ptr<sem::Type> sem::TypeScope::getType(const ast::Type& name)
+sem::TypeId sem::TypeScope::getType(const ast::Type& name)
 {
-    return nullptr;
+    return NO_TYPE;
 }
 
 
-std::shared_ptr<sem::Type> sem::TypeScope::getReturnableType(void)
+sem::TypeId sem::TypeScope::getReturnableType(void)
 {
-    return nullptr;
+    return NO_TYPE;
 }
 
 
@@ -295,10 +304,10 @@ std::string sem::TypeScope::toString(void)
 
 sem::Method* sem::NativeTypeScope::getMethod(const std::string& name)
 {
-    auto m = nativeType.nativeMethods.find(name);
+    /*auto m = nativeType.nativeMethods.find(name);
     if (m != nativeType.nativeMethods.end())
         return m->second.get();
-    else
+    else*/
         return TypeScope::getMethod(name);
 }
 

+ 25 - 8
src/Scope.h

@@ -30,7 +30,6 @@ namespace qlow
         struct Class;
         struct Method;
         struct Variable;
-        class Cast;
 
         class Scope;
         class GlobalScope;
@@ -48,7 +47,12 @@ namespace qlow
 
 class qlow::sem::Scope
 {
+protected:
+    Context& context;
 public:
+    inline Scope(Context& context) :
+        context{ context } {}
+
     virtual ~Scope(void);
     virtual Variable* getVariable(const std::string& name) = 0;
     virtual Method* getMethod(const std::string& name) = 0;
@@ -58,6 +62,8 @@ public:
         const std::vector<TypeId> argumentTypes);
 
     virtual std::string toString(void) = 0;
+
+    inline Context& getContext(void) const { return context; }
 };
 
 
@@ -66,15 +72,21 @@ class qlow::sem::GlobalScope : public Scope
 public:
     SymbolTable<Class> classes;
     SymbolTable<Method> functions;
-    OwningList<Cast> casts;
+    //OwningList<Cast> casts;
 
     Context typeContext;
 public:
+    inline GlobalScope(Context& context) :
+        Scope{ context } {}
+
     virtual Variable* getVariable(const std::string& name);
     virtual Method* getMethod(const std::string& name);
     virtual TypeId getType(const ast::Type& name);
     virtual TypeId getReturnableType(void);
 
+    inline const SymbolTable<Class>& getClasses(void) const { return classes; }
+    inline const SymbolTable<Method>& getMethods(void) const { return functions; }
+
     virtual std::string toString(void);
 };
 
@@ -83,8 +95,11 @@ class qlow::sem::NativeScope : public GlobalScope
 {
     static NativeScope instance;
 public:
-    SymbolTable<std::shared_ptr<NativeType>> types;
+    std::unordered_map<std::string, TypeId> types;
 public:
+    inline NativeScope(Context& context) :
+        GlobalScope{ context } {}
+
     virtual TypeId getType(const ast::Type& name);
 
     virtual std::string toString(void);
@@ -100,6 +115,7 @@ class qlow::sem::ClassScope : public Scope
     Class* classRef;
 public:
     inline ClassScope(Scope& parentScope, Class* classRef) :
+        Scope{ parentScope.getContext() },
         parentScope{ parentScope }, classRef{ classRef }
     {
     }
@@ -135,9 +151,10 @@ public:
 class qlow::sem::TypeScope : public Scope
 {
 protected:
-    Type& type;
+    TypeId type;
 public:
-    inline TypeScope(Type& type) :
+    inline TypeScope(Context& context, TypeId type) :
+        Scope{ context },
         type{ type }
     {
     }
@@ -152,10 +169,10 @@ public:
 
 class qlow::sem::NativeTypeScope : public TypeScope
 {
-    NativeType& nativeType;
+    TypeId nativeType;
 public:
-    inline NativeTypeScope(NativeType& type) :
-        TypeScope{ (Type&) type },
+    inline NativeTypeScope(Context& context, TypeId type) :
+        TypeScope{ context, type },
         nativeType{ type }
     {
     }

+ 34 - 24
src/ast/AstVisitor.cpp

@@ -27,7 +27,7 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureDeclara
 
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FieldDeclaration& ast, sem::Scope& scope)
 {
-    auto f = std::make_unique<sem::Field>();
+    auto f = std::make_unique<sem::Field>(scope.getContext());
     f->name = ast.name;
     auto type = scope.getType(*ast.type);
     if (type) {
@@ -78,7 +78,7 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::MethodDefiniti
 
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::VariableDeclaration& ast, sem::Scope& scope)
 {
-    auto v = std::make_unique<sem::Variable>();
+    auto v = std::make_unique<sem::Variable>(scope.getContext());
     v->name = ast.name;
     auto type = scope.getType(*ast.type);
     if (type) {
@@ -117,7 +117,7 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::DoEndBlock& as
                 throw SemanticError(SemanticError::UNKNOWN_TYPE,
                                     nvs->type->asString(),
                                     nvs->type->pos);
-            auto var = std::make_unique<sem::Variable>(std::move(type), nvs->name);
+            auto var = std::make_unique<sem::Variable>(scope.getContext(), std::move(type), nvs->name);
             body->scope.putVariable(nvs->name, std::move(var));
             continue;
         }
@@ -192,9 +192,10 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureCall& a
     sem::Method* method;
     sem::Variable* var;
     
+    // TODO rewrite types
     if (target) {
-        method = target->type->getScope().getMethod(ast.name);
-        var = target->type->getScope().getVariable(ast.name);
+        //method = target->type->getScope().getMethod(ast.name);
+        //var = target->type->getScope().getVariable(ast.name);
     }
     else {
         method = scope.getMethod(ast.name);
@@ -217,11 +218,12 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureCall& a
                 auto argument = arg->accept(*this, scope);
                 if (sem::Expression* expr =
                         dynamic_cast<sem::Expression*>(argument.get()); expr) {
-                    if (!expr->type->equals(*argTypeShouldHave))
+                    if (expr->type != argTypeShouldHave)
                         throw SemanticError(SemanticError::TYPE_MISMATCH,
-                            "argument passed to function has wrong type: '" +
-                            expr->type->asString() + "' instead of '" +
-                            argTypeShouldHave->asString() + "'",
+                            "argument passed to function has wrong type",
+                            // TODO rewrite types
+                            //expr->type->asString() + "' instead of '" +
+                            //argTypeShouldHave->asString() + "'",
                             arg->pos
                         );
                     fce->arguments.push_back(
@@ -276,21 +278,23 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureCall& a
 
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::AssignmentStatement& ast, sem::Scope& scope)
 {
-    auto as = std::make_unique<sem::AssignmentStatement>();
+    auto as = std::make_unique<sem::AssignmentStatement>(scope.getContext());
     
 //    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));
     
-    if (as->target->type->equals(*as->value->type)) {
+    if (as->target->type == as->value->type) {
         return as;
     }
     else {
         throw SemanticError(
             SemanticError::TYPE_MISMATCH,
-            "Can't assign expression of type '" + as->value->type->asString() +
-            "' to value of type '" + as->target->type->asString() + "'.",
+            "Can't assign expression of type to type.",
+            // TODO rewrite
+            //"Can't assign expression of type '" + as->value->type->asString() +
+            //"' to value of type '" + as->target->type->asString() + "'.",
             ast.pos
         );
     }
@@ -301,9 +305,9 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::ReturnStatemen
 {
     auto shouldReturn = scope.getReturnableType();
     
-    if (shouldReturn == nullptr) {
+    if (shouldReturn == sem::NO_TYPE) {
         if (ast.expr == nullptr)
-            return std::make_unique<sem::ReturnStatement>();
+            return std::make_unique<sem::ReturnStatement>(scope.getContext());
         else
             throw SemanticError(
                 SemanticError::INVALID_RETURN_TYPE,
@@ -321,16 +325,18 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::ReturnStatemen
     
     auto returnValue = unique_dynamic_cast<sem::Expression>(ast.expr->accept(*this, scope));
     
-    if (!shouldReturn->equals(*returnValue->type)) {
+    if (shouldReturn != returnValue->type) {
         throw SemanticError(
             SemanticError::INVALID_RETURN_TYPE,
-            "return value must be of type '" + shouldReturn->asString() + "' (not '" +
-            returnValue->type->asString() + "')",
+            //TODO rewrite
+            "wrong return value",
+            //"return value must be of type '" + shouldReturn->asString() + "' (not '" +
+            //returnValue->type->asString() + "')",
             ast.expr->pos
         );
     }
     
-    auto as = std::make_unique<sem::ReturnStatement>();
+    auto as = std::make_unique<sem::ReturnStatement>(scope.getContext());
     as->value = std::move(returnValue);
     return as;
 }
@@ -349,7 +355,9 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(
     auto& targetType = target->type;
     
     if (!target->isLValue()) {
-        throw NotLValue(targetType->asString(), ast.pos);
+        // TODO rewrite
+        //throw NotLValue(targetType->asString(), ast.pos);
+        throw NotLValue("type", ast.pos);
     }
     
     return std::make_unique<sem::AddressExpression>(std::move(target));
@@ -358,14 +366,14 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(
 
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::IntConst& ast, sem::Scope& scope)
 {
-    return std::make_unique<sem::IntConst>(ast.value);
+    return std::make_unique<sem::IntConst>(scope.getContext(), ast.value);
 }
 
 
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::UnaryOperation& ast, sem::Scope& scope)
 {
     auto argument = unique_dynamic_cast<sem::Expression>(ast.expr->accept(*this, scope));
-    auto ret = std::make_unique<sem::UnaryOperation>(argument->type);
+    auto ret = std::make_unique<sem::UnaryOperation>(scope.getContext(), argument->type);
             // TODO not a feasible assumption
     ret->opString = ast.opString;
     ret->side = ast.side;
@@ -379,6 +387,8 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::BinaryOperatio
     auto leftEval = unique_dynamic_cast<sem::Expression>(ast.left->accept(*this, scope));
     auto rightEval = unique_dynamic_cast<sem::Expression>(ast.right->accept(*this, scope));
     
+    throw "TODO implement";
+    /*
     sem::Method* operationMethod = leftEval->type->getScope().resolveMethod(
         ast.opString, { rightEval->type }
     );
@@ -398,13 +408,13 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::BinaryOperatio
     ret->opString = ast.opString;
     ret->left = std::move(leftEval);
     ret->right = std::move(rightEval);
-    return ret;
+    return ret;*/
 }
 
 
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::NewArrayExpression& ast, sem::Scope& scope)
 {
-    auto ret = std::make_unique<sem::NewArrayExpression>(scope.getType(*ast.type));
+    auto ret = std::make_unique<sem::NewArrayExpression>(scope.getContext(), scope.getType(*ast.type));
     return ret;
 }
 

+ 1 - 0
src/ast/Parser.cpp

@@ -8,6 +8,7 @@ qlow::ast::Ast Parser::parse(void)
     qlow::ast::Ast result;
     yyscan_t scanner;
     qlow_parser_lex_init(&scanner);
+    qlow_parser_set_in(this->stream, scanner);
     auto error = qlow_parser_parse(scanner, result, *this);
     qlow_parser_lex_destroy(scanner);
     return result;

+ 16 - 21
src/ast/lexer.l

@@ -33,29 +33,24 @@
 
 
 #define yylval qlow_parser_lval
+#define YY_EXTRA_TYPE size_t
 #define SET_TOKEN(t) (yylval_param->token = t)
 #define SET_STRING (yylval_param->string = new std::string(yytext, yyleng))
 
-/*extern "C" int yywrap(yyscan_t s)
-{
-    return 1; /* do not continue on EOF */
-/*}*/
-
-
-size_t offset;
-extern QLOW_PARSER_LTYPE qlow_parser_lloc;
-extern const char* qlow_parser_filename;
+extern "C" int qlow_parser_wrap(yyscan_t s);
 
+// TODO rewrite
 #define YY_USER_ACTION                          \
   do {                                          \
-    qlow_parser_lloc.first_line = yylineno;     \
-    qlow_parser_lloc.first_column = offset;     \
-    offset += yyleng;                           \
-    qlow_parser_lloc.last_line = yylineno;      \
-    qlow_parser_lloc.last_column = offset;      \
-    qlow_parser_lloc.filename = qlow_parser_filename; \
+    yylloc_param->first_line = yylineno;     \
+    yylloc_param->first_column = yyg->yyextra_r;     \
+    yyg->yyextra_r += yyleng;                           \
+    yylloc_param->last_line = yylineno;      \
+    yylloc_param->last_column = yyg->yyextra_r;      \
+    yylloc_param->filename = nullptr; \
   } while(0);
-
+#undef YY_USER_ACTION
+#define YY_USER_ACTION ;
 %}
 
 
@@ -75,15 +70,15 @@ UTF8CHAR [\x00-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xe
 
 <COMMENT>"/*"           commentDepth++;
 <COMMENT>"*/"           if ((--commentDepth) == 0) { BEGIN(INITIAL); };
-<COMMENT>\n             offset = 0;
+<COMMENT>\n             yyg->yyextra_r = 0;
 <COMMENT>.              ; // inside comment, ignore everything
 
-<LINE_COMMENT>\n        offset = 0; yy_pop_state(yyscanner); //yy_push_state(INITIAL);
+<LINE_COMMENT>\n        yyg->yyextra_r = 0; yy_pop_state(yyscanner); //yy_push_state(INITIAL);
 <LINE_COMMENT>.         ; // inside comment, ignore everything
 
 <STRING>"\""            yy_pop_state(yyscanner);
 <STRING>[^\"^\n]*          printf("%s\n", std::string(yytext, yyleng).c_str());
-<STRING>\n              offset = 0; SET_STRING; return UNEXPECTED_SYMBOL; 
+<STRING>\n              yyg->yyextra_r = 0; SET_STRING; return UNEXPECTED_SYMBOL; 
 
 "/*"                    yy_push_state(COMMENT, yyscanner); commentDepth = 1;
 "//"                    yy_push_state(LINE_COMMENT, yyscanner);
@@ -91,8 +86,8 @@ UTF8CHAR [\x00-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xe
 
 
 [\t ]                   ; // Space or tab ignored
-<METHOD>\n              offset = 0; return SET_TOKEN(NEW_LINE);
-\n                      offset = 0; //return SET_TOKEN(NEW_LINE);
+<METHOD>\n              yyg->yyextra_r = 0; return SET_TOKEN(NEW_LINE);
+\n                      yyg->yyextra_r = 0; //return SET_TOKEN(NEW_LINE);
 
 "class"                 return SET_TOKEN(CLASS);
 "do"                    yy_push_state(METHOD, yyscanner); return SET_TOKEN(DO);

+ 7 - 1
src/ast/syntax.y

@@ -61,6 +61,12 @@ int qlow_parser_error(qlow::CodePosition* loc, yyscan_t scan,
 }
 
 
+extern "C" int qlow_parser_wrap(yyscan_t s)
+{
+    return 1; /* do not continue on EOF */
+}
+
+
 # define YYLLOC_DEFAULT(Cur, Rhs, N)                      \
 do                                                        \
   if (N)                                                  \
@@ -188,7 +194,7 @@ while (0)
 %destructor { } <token>
 //%destructor { if ($$) delete $$ } <op>
 //%destructor { } <topLevel> // don't delete everything ;)
-%destructor { if ($$) delete $$; } <*>
+//%destructor { if ($$) delete $$; } <*>
 
 %left ASSIGN
 %left CUSTOM_OPERATOR

+ 1 - 0
src/main.cpp

@@ -11,6 +11,7 @@
 
 int main(int argc, char** argv)
 {
+    std::cout << "Hi!";
     qlow::Driver driver(argc, argv);
     return driver.run();
 

+ 2 - 2
src/makefile

@@ -8,7 +8,7 @@ LLVMCONFIG := llvm-config
 INCLUDEDIRS := -I$(shell $(LLVMCONFIG) --includedir) -I.. -Isem/ -Iast/ -I.
 CXXFLAGS := -std=c++17 $(INCLUDEDIRS) -w # -Wall -Wextra
 
-ifdef STATIC
+ifndef STATIC
 LDFLAGS := $(shell $(LLVMCONFIG) --link-static --ldflags --system-libs --libs all) -static -dead-strip -s
 else
 LDFLAGS := $(shell $(LLVMCONFIG) --ldflags --system-libs --libs all)
@@ -38,7 +38,7 @@ debug: all
 $(EXECUTABLE): $(OBJECTS)
 	$(CXX) $^ $(LDFLAGS) -o $@
 
-ast/syntax.o: ast/syntax.cpp
+ast/syntax.o: ast/syntax.cpp ast/lexer.cpp
 	$(CXX) -c -o $@ $< $(CXXFLAGS) -fno-strict-aliasing
 
 %.o: %.cpp

+ 27 - 19
src/sem/CodeGeneration.cpp

@@ -26,7 +26,7 @@ namespace qlow
 namespace gen
 {
 
-std::unique_ptr<llvm::Module> generateModule(const sem::Semantic& semantic)
+std::unique_ptr<llvm::Module> generateModule(const sem::GlobalScope& semantic)
 {
     using llvm::Module;
     using llvm::Function;
@@ -47,21 +47,23 @@ std::unique_ptr<llvm::Module> generateModule(const sem::Semantic& semantic)
 
     // create llvm structs
     // TODO implement detection of circles
-    for (auto& [name, cl] : semantic.getClasses()) {
+    for (const auto& [name, cl] : semantic.getClasses()) {
         llvm::StructType* st;
         std::vector<llvm::Type*> fields;
 #ifdef DEBUGGING
         printf("creating llvm struct for %s\n", name.c_str());
 #endif
         int llvmStructIndex = 0;
-        for (auto& [name, field] : cl->fields) {
+        
+        // TODO: rewrite
+        /*for (auto& [name, field] : cl->fields) {
             field->llvmStructIndex = llvmStructIndex;
             fields.push_back(field->type->getLlvmType(context));
             if (fields[fields.size() - 1] == nullptr)
                 throw "internal error: possible circular dependency";
             
             llvmStructIndex++;
-        }
+        }*/
         st = llvm::StructType::create(context, fields, name);
         cl->llvmType = st;
     }
@@ -80,8 +82,8 @@ std::unique_ptr<llvm::Module> generateModule(const sem::Semantic& semantic)
     auto verifyStream = llvm::raw_os_ostream(logger.debug());
     
     // create all llvm functions
-    for (auto& [name, cl] : objects.classes) {
-        for (auto& [name, method] : cl->methods) {
+    for (const auto& [name, cl] : semantic.getClasses()) {
+        for (const auto& [name, method] : cl->methods) {
             Function* func = generateFunction(module.get(), method.get());
             for (auto a : as) {
                 func->addFnAttr(a);
@@ -90,7 +92,7 @@ std::unique_ptr<llvm::Module> generateModule(const sem::Semantic& semantic)
         }
     }
     
-    for (auto& [name, method] : objects.functions) {
+    for (const auto& [name, method] : semantic.getMethods()) {
         Function* func = generateFunction(module.get(), method.get());
         for (auto a : as) {
             func->addFnAttr(a);
@@ -98,8 +100,8 @@ std::unique_ptr<llvm::Module> generateModule(const sem::Semantic& semantic)
         functions.push_back(func);
     }
 
-    for (auto& [name, cl] : objects.classes){
-        for (auto& [name, method] : cl->methods) {
+    for (const auto& [name, cl] : semantic.getClasses()){
+        for (const auto& [name, method] : cl->methods) {
             if (!method->body)
                 continue;
             
@@ -116,7 +118,7 @@ std::unique_ptr<llvm::Module> generateModule(const sem::Semantic& semantic)
 #endif
         }
     }
-    for (auto& [name, method] : objects.functions) {
+    for (const auto& [name, method] : semantic.getMethods()) {
         if (!method->body)
             continue;
         
@@ -145,19 +147,22 @@ llvm::Function* generateFunction(llvm::Module* module, sem::Method* method)
     
     Type* returnType;
     if (method->returnType)
-        returnType = method->returnType->getLlvmType(context);
+        // TODO rewrite
+        ;// returnType = method->returnType->getLlvmType(context);
     else
         returnType = llvm::Type::getVoidTy(context);
     
     std::vector<Type*> argumentTypes;
     if (method->thisExpression != nullptr) {
-        Type* enclosingType = method->thisExpression->type->getLlvmType(context);
-        argumentTypes.push_back(enclosingType);
+        // TODO rewrite
+        //Type* enclosingType = method->thisExpression->type->getLlvmType(context);
+        //argumentTypes.push_back(enclosingType);
     }
     
     for (auto& arg : method->arguments) {
-        Type* argumentType = arg->type->getLlvmType(context);
-        argumentTypes.push_back(argumentType);
+        // TODO rewrite
+        //Type* argumentType = arg->type->getLlvmType(context);
+        //argumentTypes.push_back(argumentType);
     }
     
     FunctionType* funcType = FunctionType::get(
@@ -260,6 +265,7 @@ void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Modul
     raw_fd_ostream dest(filename, errorCode, llvm::sys::fs::F_None);
     targetMachine->addPassesToEmitFile(pm, dest,
 //        llvm::LLVMTargetMachine::CGFT_ObjectFile,
+        &dest,
         llvm::TargetMachine::CGFT_ObjectFile);
 
     pm.run(*module);
@@ -302,11 +308,12 @@ llvm::Function* qlow::gen::FunctionGenerator::generate(void)
     for (auto& [name, var] : method.body->scope.getLocals()) {
         if (var.get() == nullptr)
             throw "wtf null variable";
-        if (var->type == nullptr)
+        if (var->type == sem::NO_TYPE)
             throw "wtf null type";
         
-        llvm::AllocaInst* v = builder.CreateAlloca(var->type->getLlvmType(context));
-        var->allocaInst = v;
+        // TODO rewrite
+        //llvm::AllocaInst* v = builder.CreateAlloca(var->type->getLlvmType(context));
+        //var->allocaInst = v;
     }
     
     for (auto& statement : method.body->statements) {
@@ -324,7 +331,8 @@ 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::NativeType(sem::NativeType::Type::VOID))) {
+    //if (method.returnType->equals(sem::NativeType(sem::NativeType::Type::VOID))) {
+    if (method.returnType == sem::NO_TYPE) {
         if (!getCurrentBlock()->getTerminator())
             builder.CreateRetVoid();
     }

+ 3 - 3
src/sem/Context.cpp

@@ -10,11 +10,11 @@ size_t std::hash<std::reference_wrapper<qlow::sem::Type>>::operator() (const std
 
 
 qlow::sem::TypeId Context::addType(Type&& type) {
-    if (typesMap.contains(type)) {
+    if (typesMap.find(type) != typesMap.end()) {
         return typesMap[type];
     }
     else {
-        types.emplace_back(type);
+        types.push_back(std::move(type));
         return types.size() - 1;
     }
 }
@@ -23,7 +23,7 @@ qlow::sem::TypeId Context::addType(Type&& type) {
 std::optional<std::reference_wrapper<qlow::sem::Type>> Context::getType(TypeId tid)
 {
     if (tid >= 0 && tid <= types.size()) {
-        return std::make_optional<std::reference_wrapper<qlow::sem::Type>>(*types[tid]);
+        return std::make_optional<std::reference_wrapper<qlow::sem::Type>>(types[tid]);
     }
     else {
         return std::nullopt;

+ 3 - 3
src/sem/Context.h

@@ -17,7 +17,7 @@ namespace qlow::sem
 namespace std
 {
     template<>
-    struct std::hash<std::reference_wrapper<qlow::sem::Type>>
+    struct hash<std::reference_wrapper<qlow::sem::Type>>
     {
         size_t operator() (const std::reference_wrapper<qlow::sem::Type>& t) const;
     };
@@ -27,8 +27,8 @@ namespace std
 class qlow::sem::Context
 {
 private:
-    std::vector<std::unique_ptr<Type>> types;
-    std::unordered_map<std::reference_wrapper<Type>, TypeId> typesMap;
+    std::vector<Type> types;
+    std::unordered_map<std::reference_wrapper<Type>, TypeId, std::hash<std::reference_wrapper<Type>>, std::equal_to<Type>> typesMap;
     
 public:
     

+ 9 - 7
src/sem/Semantic.cpp

@@ -16,10 +16,10 @@ namespace qlow
 namespace sem
 {
 
-std::unique_ptr<GlobalScope>
+std::pair<std::unique_ptr<Context>, std::unique_ptr<GlobalScope>>
     createFromAst(const qlow::ast::Ast& ast)
 {
-    
+    std::unique_ptr<Context> context;
     Logger& logger = Logger::getInstance();
     auto& objects = ast.getObjects();
 
@@ -28,7 +28,7 @@ std::unique_ptr<GlobalScope>
 #endif
 
     // create classes
-    std::unique_ptr<sem::GlobalScope> globalScope = std::make_unique<sem::GlobalScope>();
+    std::unique_ptr<sem::GlobalScope> globalScope = std::make_unique<sem::GlobalScope>(*context);
     for (auto& astObject : objects) {
         if (auto* cls = dynamic_cast<ast::Class*>(astObject.get()); cls) {
             globalScope->classes[cls->name] = std::make_unique<sem::Class>(cls, *globalScope);
@@ -91,7 +91,7 @@ std::unique_ptr<GlobalScope>
     for (auto& [name, semClass] : globalScope->classes) {
         for (auto& [name, method] : semClass->methods) {
             if (method->astNode->body) { // if not declaration
-                method->containingType = semClass.get();
+                method->containingClass = semClass.get();
                 method->generateThisExpression();
                 method->body = unique_dynamic_cast<sem::DoEndBlock>(method->astNode->body->accept(av, method->scope));
             }
@@ -107,7 +107,7 @@ std::unique_ptr<GlobalScope>
     printf("created all method bodies\n");
 #endif
     
-    return globalScope;
+    return std::make_pair(std::move(context), std::move(globalScope));
 }
 
 }
@@ -240,14 +240,16 @@ std::string BinaryOperation::toString(void) const
 
 std::string CastExpression::toString(void) const
 {
+    // TODO remove optional unwrapping
     return "CastExpression[" + expression->toString() + " to " +
-        targetType->toString() + "]";
+        context.getType(targetType).value().get().asString() + "]";
 }
 
 
 std::string NewArrayExpression::toString(void) const
 {
-    return "NewArrayExpression[" + arrayType->toString() + "; " +
+    // TODO remove optional unwrapping
+    return "NewArrayExpression[" + context.getType(arrayType).value().get().asString() + "; " +
         length->toString() + "]";
 }
 

+ 20 - 15
src/sem/Semantic.h

@@ -19,7 +19,7 @@ namespace qlow
 {
     namespace sem
     {
-        std::unique_ptr<GlobalScope>
+        std::pair<std::unique_ptr<Context>, std::unique_ptr<GlobalScope>>
             createFromAst(const qlow::ast::Ast& ast);
 
         struct Class;
@@ -81,20 +81,20 @@ struct qlow::sem::Class : public SemanticObject
     /// \brief generated during llvm code generation, not availab
     llvm::Type* llvmType;
 
-    inline Class(Context& context, qlow::ast::Class* astNode,
+    inline Class(qlow::ast::Class* astNode,
             GlobalScope& globalScope) :
-        SemanticObject{ context },
+        SemanticObject{ globalScope.getContext() },
         astNode{ astNode },
         name{ astNode->name },
         scope{ globalScope, this },
-        classType{ context.addType(Type::createClassType(context, this)) },
+        classType{ globalScope.getContext().addType(Type::createClassType(context, this)) },
         llvmType{ nullptr }
     {
     }
 
-    inline Class(Context& context, const std::string& nativeName,
+    inline Class(const std::string& nativeName,
             GlobalScope& globalScope) :
-        SemanticObject{ context },
+        SemanticObject{ globalScope.getContext() },
         astNode{ nullptr },
         name{ nativeName },
         scope{ globalScope, this },
@@ -116,7 +116,8 @@ struct qlow::sem::Variable : public SemanticObject
     /// instance of this variable. If it is a parameter, the parameter value
     llvm::Value* allocaInst;
     
-    Variable(void) = default;
+    inline Variable(Context& context) :
+        SemanticObject{ context } {}
     inline Variable(Context& context, TypeId type, const std::string& name) :
         SemanticObject{ context },
         type{ type },
@@ -131,6 +132,9 @@ struct qlow::sem::Variable : public SemanticObject
 
 struct qlow::sem::Field : public Variable
 {
+    inline Field(Context& context) :
+        Variable{ context } {}
+
     int llvmStructIndex;
     virtual std::string toString(void) const override;
 };
@@ -150,9 +154,9 @@ struct qlow::sem::Method : public SemanticObject
 
     llvm::Function* llvmNode;
 
-    inline Method(Context& context, Scope& parentScope,
+    inline Method(Scope& parentScope,
             TypeId returnType) :
-        SemanticObject{ context },
+        SemanticObject{ parentScope.getContext() },
         containingClass{ nullptr },
         returnType{ returnType },
         thisExpression{ nullptr },
@@ -161,9 +165,10 @@ struct qlow::sem::Method : public SemanticObject
     {
     }
     
-    /*
+    
     inline Method(ast::MethodDefinition* astNode, Scope& parentScope) :
-        containingType{ nullptr },
+        SemanticObject{ parentScope.getContext() },
+        containingClass{ nullptr },
         returnType{ parentScope.getReturnableType()},
         astNode{ astNode },
         name{ astNode->name },
@@ -171,7 +176,7 @@ struct qlow::sem::Method : public SemanticObject
         thisExpression{ nullptr },
         body{ nullptr }
     {
-    }*/
+    }
     
     void generateThisExpression(void);
     
@@ -211,8 +216,8 @@ struct qlow::sem::DoEndBlock : public Statement
     LocalScope scope;
     OwningList<Statement> statements;
 
-    inline DoEndBlock(Context& context, LocalScope& parentScope) :
-        Statement{ context },
+    inline DoEndBlock(LocalScope& parentScope) :
+        Statement{ parentScope.getContext() },
         scope{ parentScope } {}
     
     virtual llvm::Value* accept(qlow::StatementVisitor&, gen::FunctionGenerator&) override;
@@ -470,7 +475,7 @@ struct qlow::sem::IntConst : public Expression
     unsigned long long value;
 
     inline IntConst(Context& context, unsigned long long value) :
-        Expression{ context.addType(/* integer */) },
+        Expression{ context, context.addType(Type::createNativeType(context, "integer")) },
         value{ value }
     {
     }

+ 43 - 8
src/sem/Type.cpp

@@ -36,19 +36,20 @@ std::string Type::asString(void) const
     return std::visit(
         [&] (const auto& t) -> std::string {
             using T = std::decay_t<decltype(t)>;
-            if constexpr (std::is_same<T, NativeType>) {
+            if constexpr (std::is_same<T, NativeType>::value) {
                 return this->name;
             }
-            else if constexpr (std::is_same<T, ClassType>) {
+            else if constexpr (std::is_same<T, ClassType>::value) {
                 return this->name;
             }
-            else if constexpr (std::is_same<T, PointerType>) {
-                auto& context = t.targetType.getContext();
-                return context.getType(t.targetType) + "*";
+            else if constexpr (std::is_same<T, PointerType>::value) {
+                // TODO rewrite
+                //return context.getType(t.targetType) + "*";
+                return "*";
             }
-            else if constexpr (std::is_same<T, ArrayType>) {
-                auto& context = t.targetType.getContext();
-                return "[" + context.getType(t.targetType) + "]";
+            else if constexpr (std::is_same<T, ArrayType>::value) {
+                //return "[" + context.getType(t.targetType) + "]";
+                return "[]";
             }
         }
         ,
@@ -56,17 +57,51 @@ std::string Type::asString(void) const
     );
 }
 
+
+size_t Type::hash(void) const
+{
+    // TODO implement
+    return 0;
+}
+
+
 bool Type::operator==(const Type& other) const
 {
     return this->name == other.name &&
            this->type == other.type;
 }
 
+
+qlow::sem::Class* Type::getClass(void) const
+{
+    try {
+        return std::get<ClassType>(type).classType;
+    }
+    catch(std::bad_variant_access& bva) {
+        return nullptr;
+    }
+}
+
+
+llvm::Type* Type::getLLVMType(llvm::LLVMContext* context)
+{
+    // TODO implement
+    return nullptr;
+}
+
+
+Type Type::createNativeType(Context& c, std::string name)
+{
+    return Type{ Union{ NativeType{} }, std::move(name) };
+}
+
+
 Type Type::createClassType(Context& c, Class* classType)
 {
     return Type{ Union{ ClassType{ classType }}};
 }
 
+
 Type Type::createPointerType(Context& c, TypeId pointsTo)
 {
     return Type{ Union{ PointerType{ pointsTo }}};

+ 20 - 1
src/sem/Type.h

@@ -5,12 +5,19 @@
 #include <string>
 #include <climits>
 
+namespace llvm {
+    class Value;
+    class Type;
+    class LLVMContext;
+}
+
 namespace qlow::sem
 {
     struct SemanticObject;
     class Type;
     
     using TypeId = size_t;
+    const TypeId NO_TYPE = std::numeric_limits<TypeId>::max();
 
     // forward declarations to other files
     struct Class;
@@ -68,21 +75,25 @@ private:
 
     struct NativeType
     {
+        inline bool operator==(const NativeType& other) const { return true; }
     };
 
     struct ClassType
     {
         Class* classType;
+        inline bool operator==(const ClassType& other) const { return classType == other.classType; }
     };
 
     struct PointerType
     {
         TypeId targetType;
+        inline bool operator==(const PointerType& other) const { return targetType == other.targetType; }
     };
 
     struct ArrayType 
     {
         TypeId targetType;
+        inline bool operator==(const ArrayType& other) const { return targetType == other.targetType; }
     };
 
     using Union = std::variant<NativeType, ClassType, PointerType, ArrayType>;
@@ -91,6 +102,9 @@ private:
     inline Type(Union type) :
         type{ type } {}
 
+    inline Type(Union type, std::string name) :
+        name{ std::move(name) }, type{ type } {}
+
 public:
     Kind getKind(void) const;
     std::string asString(void) const;
@@ -98,6 +112,11 @@ public:
 
     bool operator == (const Type& other) const;
 
+    Class* getClass(void) const;
+
+    llvm::Type* getLLVMType(llvm::LLVMContext* context);
+
+    static Type createNativeType(Context& c, std::string name);
     static Type createClassType(Context& c, Class* classType);
     static Type createPointerType(Context& c, TypeId pointsTo);
     static Type createArrayType(Context& c, TypeId pointsTo);
@@ -162,7 +181,7 @@ public:
     virtual std::string asString(void) const = 0;
     virtual Scope& getScope(void) = 0;
     
-    virtual llvm::Type* getLlvmType(llvm::LLVMContext& context) const = 0;
+    virtual y = 0;
     
     virtual bool equals(const Type& other) const;
 

+ 0 - 86
src/tests/VisitorTest.cpp

@@ -1,86 +0,0 @@
-#include "../Visitor.h"
-#include <iostream>
-
-using namespace qlow;
-
-
-class Animal;
-class Pig;
-class Cow;
-class Horse;
-
-
-class AnimalVisitor : public Visitor<void, Pig, Cow, Horse>
-//    public Visitor<
-//        // visitable types
-//        Pig, Cow, Horse
-//    >
-{
-public:
-
-    void visit(Pig& p) override
-    {
-        std::cout << "Hey Piggy" << std::endl;
-    }
-
-    void visit(Cow& p) override
-    {
-        std::cout << "Hay Cow" << std::endl;
-    }
-
-    void visit(Horse& p) override
-    {
-        std::cout << "Hiy Ross" << std::endl;
-    }
-};
-
-
-class Animal : public Visitable<AnimalVisitor>
-{
-};
-
-
-class Pig : public Animal
-{
-public:
-    inline void accept(AnimalVisitor& av) final
-    {
-        return av.visit(*this);
-    }
-};
-
-
-class Cow : public Animal
-{
-public:
-    inline void accept(AnimalVisitor& av) final
-    {
-        return av.visit(*this);
-    }
-};
-
-
-class Horse : public Animal
-{
-public:
-    inline void accept(AnimalVisitor& av) final
-    {
-        return av.visit(*this);
-    }
-};
-
-
-
-int main()
-{
-    Animal* animal = new Pig();
-    AnimalVisitor av;
-
-    animal->accept(av);
-    return 0;
-}
-
-
-
-
-