Explorar o código

wow yay works good now

Nicolas Winkler %!s(int64=6) %!d(string=hai) anos
pai
achega
803bc49d28
Modificáronse 22 ficheiros con 264 adicións e 121 borrados
  1. 1 0
      src/Ast.cpp
  2. 21 0
      src/Ast.h
  3. 19 1
      src/AstVisitor.cpp
  4. 2 0
      src/AstVisitor.h
  5. 1 0
      src/Builtin.cpp
  6. 43 12
      src/CodeGeneration.cpp
  7. 1 1
      src/CodeGeneration.h
  8. 40 2
      src/CodegenVisitor.cpp
  9. 2 0
      src/CodegenVisitor.h
  10. 58 14
      src/Driver.cpp
  11. 3 1
      src/Driver.h
  12. 7 7
      src/Scope.cpp
  13. 2 1
      src/Semantic.cpp
  14. 16 0
      src/Semantic.h
  15. 3 2
      src/Type.cpp
  16. 2 0
      src/Type.h
  17. 1 0
      src/TypeVisitor.cpp
  18. 1 0
      src/lexer.l
  19. 4 4
      src/main.cpp
  20. 1 1
      src/makefile
  21. 16 1
      src/parser.y
  22. 20 74
      src/test.qlw

+ 1 - 0
src/Ast.cpp

@@ -27,6 +27,7 @@ ACCEPT_DEFINITION(VariableDeclaration, StructureVisitor)
 ACCEPT_DEFINITION(Statement, StructureVisitor)
 ACCEPT_DEFINITION(DoEndBlock, StructureVisitor)
 ACCEPT_DEFINITION(IfElseBlock, StructureVisitor)
+ACCEPT_DEFINITION(WhileBlock, StructureVisitor)
 ACCEPT_DEFINITION(Expression, StructureVisitor)
 ACCEPT_DEFINITION(FeatureCall, StructureVisitor)
 ACCEPT_DEFINITION(AssignmentStatement, StructureVisitor)

+ 21 - 0
src/Ast.h

@@ -60,6 +60,7 @@ namespace qlow
         
         struct DoEndBlock;
         struct IfElseBlock;
+        struct WhileBlock;
 
         struct Expression;
 
@@ -292,6 +293,25 @@ struct qlow::ast::IfElseBlock : public Statement
 };
 
 
+struct qlow::ast::WhileBlock : public Statement
+{
+    std::unique_ptr<Expression> condition;
+    std::unique_ptr<DoEndBlock> body;
+    
+    inline WhileBlock(std::unique_ptr<Expression> condition,
+                      std::unique_ptr<DoEndBlock> body,
+                      const CodePosition& cp) :
+        AstObject{ cp },
+        Statement{ cp },
+        condition{ std::move(condition) },
+        body{ std::move(body) }
+    {
+    }
+
+    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
+};
+
+
 struct qlow::ast::Expression : public virtual AstObject
 {
     inline Expression(const CodePosition& cp) :
@@ -396,6 +416,7 @@ struct qlow::ast::Operation : public Expression
         ASTERISK,
         SLASH,
         EQUALS,
+        NOT_EQUALS,
         AND,
         OR,
         XOR,

+ 19 - 1
src/AstVisitor.cpp

@@ -141,7 +141,7 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::IfElseBlock& a
     if (!dynamic_cast<sem::DoEndBlock*>(ifB.get())
         || !dynamic_cast<sem::DoEndBlock*>(eB.get())
         || !dynamic_cast<sem::Expression*>(condition.get()))
-        throw "internal error";
+        throw "internal error, invalid if block";
     
     auto condExpr = unique_dynamic_cast<sem::Expression>(std::move(condition));
     auto ifBBlock = unique_dynamic_cast<sem::DoEndBlock>(std::move(ifB));
@@ -153,6 +153,24 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::IfElseBlock& a
 }
 
 
+std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::WhileBlock& ast, sem::Scope& scope)
+{
+    auto condition = ast.condition->accept(*this, scope);
+    auto body = ast.body->accept(*this, scope);
+    
+    if (!dynamic_cast<sem::DoEndBlock*>(body.get()) ||
+        !dynamic_cast<sem::Expression*>(condition.get()))
+        throw "internal error, invalid while block";
+    
+    auto condExpr = unique_dynamic_cast<sem::Expression>(std::move(condition));
+    auto bodyblock = unique_dynamic_cast<sem::DoEndBlock>(std::move(body));
+    
+    auto wb = std::make_unique<sem::WhileBlock>(std::move(condExpr), std::move(bodyblock));
+    
+    return wb;
+}
+
+
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::Expression& ast, sem::Scope& scope)
 {
     throw "visit(Expression) shouldn't be called";

+ 2 - 0
src/AstVisitor.h

@@ -68,6 +68,7 @@ class qlow::StructureVisitor :
         ast::Statement,
         ast::DoEndBlock,
         ast::IfElseBlock,
+        ast::WhileBlock,
         ast::Expression,
         ast::FeatureCall,
         ast::AssignmentStatement,
@@ -90,6 +91,7 @@ public:
     ReturnType visit(ast::Statement& ast, sem::Scope& scope) override;
     ReturnType visit(ast::DoEndBlock& ast, sem::Scope& scope) override;
     ReturnType visit(ast::IfElseBlock& ast, sem::Scope& scope) override;
+    ReturnType visit(ast::WhileBlock& ast, sem::Scope& scope) override;
     ReturnType visit(ast::Expression& ast, sem::Scope& scope) override;
     ReturnType visit(ast::FeatureCall& ast, sem::Scope& scope) override;
     ReturnType visit(ast::AssignmentStatement& ast, sem::Scope& scope) override;

+ 1 - 0
src/Builtin.cpp

@@ -1,5 +1,6 @@
 #include "Builtin.h"
 #include "Scope.h"
+#include "Type.h"
 
 using namespace qlow;
 

+ 43 - 12
src/CodeGeneration.cpp

@@ -2,6 +2,7 @@
 
 #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>
@@ -12,6 +13,7 @@
 #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;
@@ -60,6 +62,7 @@ std::unique_ptr<llvm::Module> generateModule(const sem::GlobalScope& objects)
     }
     
     std::vector<llvm::Function*> functions;
+    auto verifyStream = llvm::raw_os_ostream(logger.debug());
     
     // create all llvm functions
     for (auto& [name, cl] : objects.classes) {
@@ -76,7 +79,10 @@ std::unique_ptr<llvm::Module> generateModule(const sem::GlobalScope& objects)
         for (auto& [name, method] : cl->methods) {
             FunctionGenerator fg(*method, module.get());
             Function* f = fg.generate();
-            llvm::verifyFunction(*f, &llvm::errs());
+            logger.debug() << "verifying function: " << method->name << std::endl;
+            bool corrupt = llvm::verifyFunction(*f, &verifyStream);
+            if (corrupt)
+                throw "corrupt llvm function";
 #ifdef DEBUGGING
             printf("verified function: %s\n", method->name.c_str());
 #endif
@@ -85,7 +91,10 @@ std::unique_ptr<llvm::Module> generateModule(const sem::GlobalScope& objects)
     for (auto& [name, method] : objects.functions) {
         FunctionGenerator fg(*method, module.get());
         Function* f = fg.generate();
-        llvm::verifyFunction(*f, &llvm::errs());
+        logger.debug() << "verifying function: " << method->name << std::endl;
+        bool corrupt = llvm::verifyFunction(*f, &verifyStream);
+        if (corrupt)
+            throw "corrupt llvm function";
 #ifdef DEBUGGING
         printf("verified function: %s\n", method->name.c_str());
 #endif
@@ -136,21 +145,26 @@ llvm::Function* generateFunction(llvm::Module* module, sem::Method* method)
 }
 
 
-void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Module> module)
+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;
 
-
-    printf("verifying mod\n");
-    module->print(llvm::errs(), nullptr);
-    llvm::verifyModule(*module);
-    printf("mod verified\n");
-
+    Logger& logger = Logger::getInstance();
+    logger.debug() << "verifying mod" << std::endl;
+    auto ostr = llvm::raw_os_ostream(logger.debug());
+    module->print(ostr, nullptr);
+    bool broken = llvm::verifyModule(*module);
+    
+    if (broken)
+        throw "invalid llvm module";
+    
+    logger.debug() << "mod verified" << std::endl;
 
     llvm::InitializeAllTargetInfos();
     llvm::InitializeAllTargets();
@@ -159,6 +173,19 @@ void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Modul
     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[] = "";
@@ -167,8 +194,9 @@ void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Modul
     std::string targetTriple = llvm::sys::getDefaultTargetTriple();
     const Target* target = TargetRegistry::lookupTarget(targetTriple, error);
 
-    if (!target)
-        fprintf(stderr, "could not create target: %s", error.c_str());
+    if (!target) {
+        logger.debug() << "could not create target: " << error << std::endl;
+    }
 
     TargetOptions targetOptions;
     auto relocModel = llvm::Optional<llvm::Reloc::Model>();
@@ -239,7 +267,10 @@ llvm::Function* qlow::gen::FunctionGenerator::generate(void)
     //Value* val = llvm::ConstantFP::get(context, llvm::APFloat(5.0));
     
     builder.SetInsertPoint(getCurrentBlock());
-    builder.CreateRetVoid();
+    if (method.returnType->equals(sem::Type::VOID)) {
+        if (!getCurrentBlock()->getTerminator())
+            builder.CreateRetVoid();
+    }
 
     return func;
 }

+ 1 - 1
src/CodeGeneration.h

@@ -14,7 +14,7 @@ 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);
+    void generateObjectFile(const std::string& name, std::unique_ptr<llvm::Module> module, int optLevel);
 
     class FunctionGenerator;
 }

+ 40 - 2
src/CodegenVisitor.cpp

@@ -49,6 +49,8 @@ std::pair<llvm::Value*, sem::Type*> ExpressionVisitor::visit(sem::BinaryOperatio
             return { builder.CreateSDiv(left, right, "add"), Type::INTEGER };
         case ast::Operation::Operator::EQUALS:
             return { builder.CreateICmpEQ(left, right, "equals"), Type::BOOLEAN };
+        case ast::Operation::Operator::NOT_EQUALS:
+            return { builder.CreateICmpNE(left, right, "not_equals"), Type::BOOLEAN };
         case ast::Operation::Operator::AND:
             return { builder.CreateAnd(left, right, "and"), Type::BOOLEAN };
         case ast::Operation::Operator::OR:
@@ -144,18 +146,54 @@ llvm::Value* StatementVisitor::visit(sem::IfElseBlock& ifElseBlock,
     fg.pushBlock(thenB);
     ifElseBlock.ifBlock->accept(*this, fg);
     builder.SetInsertPoint(thenB);
-    builder.CreateBr(merge);
+    if (!thenB->getTerminator())
+        builder.CreateBr(merge);
     fg.popBlock();
     fg.pushBlock(elseB);
     ifElseBlock.elseBlock->accept(*this, fg);
     builder.SetInsertPoint(elseB);
-    builder.CreateBr(merge);
+    if (!elseB->getTerminator())
+        builder.CreateBr(merge);
     fg.popBlock();
     fg.popBlock();
     fg.pushBlock(merge);
 }
 
 
+llvm::Value* StatementVisitor::visit(sem::WhileBlock& whileBlock,
+        qlow::gen::FunctionGenerator& fg)
+{
+    using llvm::Value;
+    using llvm::BasicBlock;
+    
+    llvm::IRBuilder<> builder(fg.getContext());
+    builder.SetInsertPoint(fg.getCurrentBlock());
+    
+    llvm::Function* function = fg.getCurrentBlock()->getParent();
+    
+    BasicBlock* startloop = BasicBlock::Create(fg.getContext(), "startloop", function);
+    BasicBlock* body = BasicBlock::Create(fg.getContext(), "loopbody", function);
+    BasicBlock* merge = BasicBlock::Create(fg.getContext(), "merge", function);
+    
+    
+    //builder.CreateCondBr(boolCond, body, merge);
+    builder.CreateBr(startloop);
+    fg.pushBlock(startloop);
+    builder.SetInsertPoint(startloop);
+    auto [condition, condType] = whileBlock.condition->accept(fg.expressionVisitor, builder);
+    Value* boolCond = builder.CreateIntCast(condition, llvm::Type::getInt1Ty(fg.getContext()), false);
+    builder.CreateCondBr(condition, body, merge);
+    fg.popBlock();
+    
+    fg.pushBlock(body);
+    whileBlock.body->accept(*this, fg);
+    builder.SetInsertPoint(body);
+    builder.CreateBr(startloop);
+    fg.popBlock();
+    fg.pushBlock(merge);
+}
+
+
 llvm::Value* StatementVisitor::visit(sem::AssignmentStatement& assignment,
         qlow::gen::FunctionGenerator& fg)
 {

+ 2 - 0
src/CodegenVisitor.h

@@ -58,6 +58,7 @@ class qlow::StatementVisitor :
 
         sem::DoEndBlock,
         sem::IfElseBlock,
+        sem::WhileBlock,
         sem::AssignmentStatement,
         sem::ReturnStatement,
         sem::FeatureCallStatement
@@ -66,6 +67,7 @@ class qlow::StatementVisitor :
 public:
     llvm::Value* visit(sem::DoEndBlock& node, gen::FunctionGenerator&) override;
     llvm::Value* visit(sem::IfElseBlock& node, gen::FunctionGenerator&) override;
+    llvm::Value* visit(sem::WhileBlock& node, gen::FunctionGenerator&) override;
     llvm::Value* visit(sem::AssignmentStatement& node, gen::FunctionGenerator&) override;
     llvm::Value* visit(sem::ReturnStatement& node, gen::FunctionGenerator&) override;
     llvm::Value* visit(sem::FeatureCallStatement& node, gen::FunctionGenerator&) override;

+ 58 - 14
src/Driver.cpp

@@ -21,7 +21,6 @@ Options Options::parseOptions(int argc, char** argv)
     {
         {"-S",              &Options::emitAssembly},
         {"--emit-assembly", &Options::emitAssembly},
-        {"-O3",             &Options::emitAssembly},
         {"-L",              &Options::emitLlvm},
         {"--emit-llvm",     &Options::emitLlvm},
     };
@@ -42,6 +41,14 @@ Options Options::parseOptions(int argc, char** argv)
                 throw "Please specify a filename after '-o'";
             }
         }
+        else if (arg.rfind("-O", 0) == 0) {
+            if (arg.size() > 2) {
+                options.optLevel = std::stoi(arg.substr(2));
+            }
+            else {
+                options.optLevel = 2;
+            }
+        }
         else {
             options.infiles.push_back(std::move(arg));
         }
@@ -63,6 +70,8 @@ int Driver::run(void)
     //logger.logError("driver not yet implemented", {options.emitAssembly ? "asm" : "noasm", 10, 11, 12, 13});
     
     std::vector<std::unique_ptr<qlow::ast::AstObject>> objects;
+    bool errorOccurred = false;
+    
     for (auto& filename : options.infiles) {
         std::FILE* file = std::fopen(filename.c_str(), "r");
         ::qlow_parser_filename = filename.c_str();
@@ -75,17 +84,25 @@ int Driver::run(void)
         }
         catch (const CompileError& ce) {
             ce.print(logger);
-            return 1;
+            errorOccurred = true;
         }
         catch (const char* errMsg) {
             logger.logError(errMsg);
-            return 1;
+            errorOccurred = true;
+        }
+        catch (...) {
+            logger.logError("an unknown error occurred.");
+            errorOccurred = true;
         }
         
         if (file)
             std::fclose(file);
     }
     
+    if (errorOccurred) {
+        logger << "Aborting due to syntax errors." << std::endl;
+        return 1;
+    }
     
     std::unique_ptr<qlow::sem::GlobalScope> semClasses = nullptr;
     try {
@@ -94,17 +111,30 @@ int Driver::run(void)
     }
     catch(SemanticError& se) {
         se.print(logger);
-        return 1;
+        errorOccurred = true;
     }
     catch(const char* err) {
         logger.logError(err);
+        errorOccurred = true;
+    }
+    catch (...) {
+        logger.logError("an unknown error occurred.");
+        errorOccurred = true;
     }
+    
+    if (errorOccurred) {
+        logger << "Aborting due to semantic errors." << std::endl;
+        return 1;
+    }
+    
 
     for (auto& [a, b] : semClasses->classes) {
         logger.debug() << a << ": " << b->toString() << std::endl;
     }
+    
+    
 
-    auto main = semClasses->classes.find("Main");
+    /*auto main = semClasses->classes.find("Main");
     qlow::sem::Class* mainClass = nullptr;
     if (main == semClasses->classes.end()) {
         logger.logError("No Main class found");
@@ -112,15 +142,13 @@ int Driver::run(void)
     }
     else {
         mainClass = main->second.get();
-    }
+    }*/
     
-    auto mainmain = mainClass->methods.find("main");
-    qlow::sem::Method* mainMethod = nullptr;
-    if (mainmain == mainClass->methods.end()) {
-        //throw "No main method found inside Main class!";
-    }
-    else {
-        mainMethod = mainmain->second.get();
+    auto* mainMethod = semClasses->getMethod("main");
+    if (mainMethod == nullptr && false) {
+        // TODO handle main ckeck well
+        logger.logError("no main method found");
+        return 1;
     }
     
     logger.debug() << "starting code generation!" << std::endl;
@@ -132,8 +160,24 @@ int Driver::run(void)
     }
     catch (const char* err) {
         logger.logError(err);
+        return 1;
+    }
+    catch (...) {
+        logger.logError("unknown error during code generation");
+        return 1;
+    }
+    
+    try {
+        qlow::gen::generateObjectFile(options.outfile, std::move(mod), options.optLevel);
+    }
+    catch (const char* msg) {
+        logger.logError(msg);
+        return 1;
+    }
+    catch (...) {
+        logger.logError("unknown error during object file creation");
+        return 1;
     }
-    qlow::gen::generateObjectFile("obj.o", std::move(mod));
     
     logger.debug() << "object exported!" << std::endl;
     

+ 3 - 1
src/Driver.h

@@ -28,6 +28,8 @@ struct qlow::Options
     std::string outfile = "a.out";
     std::vector<std::string> infiles;
     
+    int optLevel = 0;
+    
     static Options parseOptions(int argc, char** argv);
 };
 
@@ -42,7 +44,7 @@ public:
     int run(void);
     
     /// \brief runs the parser over a given stream
-    /// \warning Don't call concurrently. Not supported!
+    /// \warning Don't call concurrently. Not (yet) supported!
     std::vector<std::unique_ptr<qlow::ast::AstObject>> parseFile(FILE* file);
 };
 

+ 7 - 7
src/Scope.cpp

@@ -32,17 +32,17 @@ sem::Type* sem::GlobalScope::getType(const ast::Type& name)
         return new sem::ArrayType(getType(*arr->arrayType));
     }
     
-    const auto* classType = dynamic_cast<const ast::ClassType*>(&name);
-   
-    if (!classType)
-        throw "internal error";
-    
-    
     auto native = NativeScope::getInstance().getType(name);
     if (native) {
         return native;
     }
     
+    const auto* classType = dynamic_cast<const ast::ClassType*>(&name);
+   
+    if (!classType)
+        throw "internal error, non class-type top-level type";
+    
+    
     
     auto t = classes.find(classType->typeName);
     if (t != classes.end())
@@ -79,7 +79,7 @@ sem::Type* sem::NativeScope::getType(const ast::Type& name)
     const auto* classType = dynamic_cast<const ast::ClassType*>(&name);
    
     if (!classType)
-        throw "internal error";
+        return sem::Type::VOID;
     
     
     auto t = types.find(classType->typeName);

+ 2 - 1
src/Semantic.cpp

@@ -61,7 +61,7 @@ std::unique_ptr<GlobalScope>
             }
             else {
                 // if a feature is neither a method nor a field, something went horribly wrong
-                throw "internal error";
+                throw "internal error, feature neither field nor method";
             }
         }
     }
@@ -176,6 +176,7 @@ ACCEPT_DEFINITION(IntConst, ExpressionVisitor, std::pair<llvm::Value* COMMA Type
 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&) 
+ACCEPT_DEFINITION(WhileBlock, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&) 
 ACCEPT_DEFINITION(ReturnStatement, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&) 
 ACCEPT_DEFINITION(FeatureCallStatement, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&) 
 

+ 16 - 0
src/Semantic.h

@@ -32,6 +32,7 @@ namespace qlow
 
         struct DoEndBlock;
         struct IfElseBlock;
+        struct WhileBlock;
         struct FeatureCallStatement;
         struct AssignmentStatement;
         struct ReturnStatement;
@@ -192,6 +193,21 @@ struct qlow::sem::IfElseBlock : public Statement
 };
 
 
+struct qlow::sem::WhileBlock : public Statement
+{
+    std::unique_ptr<Expression> condition;
+    std::unique_ptr<DoEndBlock> body;
+    inline WhileBlock(std::unique_ptr<Expression> condition,
+                       std::unique_ptr<DoEndBlock> body) :
+        condition{ std::move(condition) },
+        body{ std::move(body) }
+    {
+    }
+    
+    virtual llvm::Value* accept(qlow::StatementVisitor&, gen::FunctionGenerator&) override;
+};
+
+
 struct qlow::sem::AssignmentStatement : public Statement 
 {
     std::unique_ptr<Expression> target;

+ 3 - 2
src/Type.cpp

@@ -21,6 +21,7 @@ bool sem::Type::equals(const Type* other) const
 }
 
 
+sem::Type* sem::Type::VOID = new sem::NativeType(sem::NativeType::Type::VOID);
 sem::Type* sem::Type::INTEGER = new sem::NativeType(sem::NativeType::Type::INTEGER);
 sem::Type* sem::Type::BOOLEAN = new sem::NativeType(sem::NativeType::Type::BOOLEAN);
 
@@ -63,8 +64,8 @@ bool sem::ArrayType::equals(const Type* other) const
 llvm::Type* sem::NativeType::getLlvmType (llvm::LLVMContext& context) const
 {
     switch (type) {
-        /*case Kind::NULL_TYPE:
-            return llvm::Type::getVoidTy(context);*/
+        case VOID:
+            return llvm::Type::getVoidTy(context);
         case INTEGER:
             return llvm::Type::getInt32Ty(context);
         case BOOLEAN:

+ 2 - 0
src/Type.h

@@ -42,6 +42,7 @@ public:
     
     virtual bool equals(const Type* other) const;
     
+    static Type* VOID;
     static Type* INTEGER;
     static Type* BOOLEAN;
 };
@@ -90,6 +91,7 @@ class qlow::sem::NativeType : public Type
 {
 public:
     enum Type {
+        VOID,
         INTEGER,
         BOOLEAN
     };

+ 1 - 0
src/TypeVisitor.cpp

@@ -1,4 +1,5 @@
 #include "TypeVisitor.h"
+#include "Type.h"
 
 using namespace qlow;
 

+ 1 - 0
src/lexer.l

@@ -106,6 +106,7 @@ UTF8CHAR [\x00-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xe
 "."                     return SET_TOKEN(DOT);
 
 "=="                    return SET_TOKEN(EQUALS);
+"!="                    return SET_TOKEN(NOT_EQUALS);
 "and"                   return SET_TOKEN(AND);
 "or"                    return SET_TOKEN(OR);
 "xor"                   return SET_TOKEN(XOR);

+ 4 - 4
src/main.cpp

@@ -16,7 +16,7 @@ extern int qlow_parser_parse(void);
 
 int main(int argc, char** argv)
 {
-    int c;
+    /*int c;
     while ((c = getopt(argc, argv, "c:")) != -1) {
         switch (c) {
             case 'c':
@@ -25,11 +25,11 @@ int main(int argc, char** argv)
             default:
                 printf("ay: %c\n", c);
         }
-    }
+    }*/
     
     qlow::Driver driver(argc, argv);
-    driver.run();
-    
+    return driver.run();
+
     return 0;
     /*
     {

+ 1 - 1
src/makefile

@@ -54,6 +54,6 @@ parser.o: parser.cpp
 
 .PHONY: clean
 clean:
-	rm -f $(EXECUTABLE) *.o parser.cpp parser.hpp lexer.cpp
+	rm -f $(EXECUTABLE) $(OBJECTS) parser.cpp parser.hpp lexer.cpp
 
 

+ 16 - 1
src/parser.y

@@ -101,6 +101,7 @@ typedef qlow::CodePosition QLOW_PARSER_LTYPE;
     qlow::ast::ArgumentDeclaration* argumentDeclaration;
     qlow::ast::DoEndBlock* doEndBlock;    
     qlow::ast::IfElseBlock* ifElseBlock;    
+    qlow::ast::WhileBlock* whileBlock;    
     qlow::ast::Statement* statement;
     qlow::ast::Expression* expression;
     qlow::ast::Operation::Operator op;
@@ -129,7 +130,7 @@ typedef qlow::CodePosition QLOW_PARSER_LTYPE;
 %token <token> TRUE FALSE
 %token <token> CLASS DO END IF ELSE WHILE RETURN NEW
 %token <token> NEW_LINE
-%token <token> SEMICOLON COLON COMMA DOT ASSIGN
+%token <token> SEMICOLON COLON COMMA DOT ASSIGN EQUALS NOT_EQUALS
 %token <token> ROUND_LEFT ROUND_RIGHT SQUARE_LEFT SQUARE_RIGHT
 %token <string> UNEXPECTED_SYMBOL
 
@@ -146,6 +147,7 @@ typedef qlow::CodePosition QLOW_PARSER_LTYPE;
 %type <argumentDeclaration> argumentDeclaration
 %type <doEndBlock> doEndBlock
 %type <ifElseBlock> ifElseBlock 
+%type <whileBlock> whileBlock
 %type <statement> statement
 %type <expression> expression operationExpression paranthesesExpression
 %type <op> operator
@@ -337,6 +339,13 @@ ifElseBlock:
         delete $4;
         delete $6;
     };
+    
+whileBlock:
+    WHILE expression doEndBlock {
+        $$ = new WhileBlock(std::unique_ptr<Expression>($2),
+                            std::unique_ptr<DoEndBlock>($3), @$);
+        $2 = nullptr; $3 = nullptr;
+    };
 
 
 statements:
@@ -383,6 +392,10 @@ statement:
         $$ = $1;
     }
     |
+    whileBlock statementEnd {
+        $$ = $1;
+    }
+    |
     error statementEnd {
         $$ = nullptr;
         //printf("error happened here (%s): %d\n", qlow_parser_filename, @1.first_line);
@@ -505,6 +518,8 @@ operator:
     |
     EQUALS { $$ = qlow::ast::Operation::Operator::EQUALS; }
     |
+    NOT_EQUALS { $$ = qlow::ast::Operation::Operator::NOT_EQUALS; }
+    |
     AND { $$ = qlow::ast::Operation::Operator::AND; }
     |
     OR { $$ = qlow::ast::Operation::Operator::OR; }

+ 20 - 74
src/test.qlw

@@ -1,81 +1,27 @@
 
-class Main
-    hoi: Fudi 
-    //gaga -> Main;
-
-    fop: FF do
-        var: Integer
-        var := 5
-        var := 10 + 4 * 6 + 1
-
-        /*
-        // initialize variable
-        var := 5;
-        var := 102 + var * var;
-        var := 102 + var * var;
-
-        // more additions
-        var := 102 + var * var;
-        var := 102 + var * var;
-        var := 102 + var * var;
-        var := 102 + var * var;
-        */
-    end
-
-    mainn: Integer do
-        fop
-        return 12
-    end
-end
-
-fibonacci(i: Integer): Integer do
-    if i == 0 do
-        return 0
-    else
-    end
-    if i == 1 do
-        return 1
-    else
-    end
-    return fibonacci(i - 1) + fibonacci(i - 2)
-end
-
-
-class FF
-    field1: Integer
-    field2: Integer
-
-    calc: Integer do
-        return 100000
-    end
-
-    verdoppel(x: Integer): Integer do
-        return x + x
-    end
-
-    istfumf(x: Integer): Integer do
-        if x == 5 do
-            return 1
-        else
-            return 0
-        end
-        return 100;
-    end
-
-    sum_func: Integer do
-        variable: Integer
-        variable := verdoppel(51)
-        variable := istfumf(variable)
-        variable := 3 == 3
-        return variable + 2
-    end
+fast_fibonacci(i: Integer): Integer do
+    a: Integer
+    b: Integer
+    temp: Integer
+    count: Integer
+    count := i
+    a := 0
+    b := 1
+    while count != 0 do
+        temp := a
+        a := a + b
+        b := temp
+        count := count - 1
+    end
+    return a
 end
 
-
-class Fudi
+/*
+main do
+    value: Integer
+    value := fast_fibonacci(5)
 end
-
-
+*/