浏览代码

wooorks! yay

Nicolas Winkler 6 年之前
父节点
当前提交
16becadb57
共有 18 个文件被更改,包括 260 次插入149 次删除
  1. 1 1
      src/Ast.cpp
  2. 17 1
      src/Ast.h
  3. 35 7
      src/AstVisitor.cpp
  4. 2 2
      src/AstVisitor.h
  5. 13 5
      src/Builtin.cpp
  6. 2 3
      src/Builtin.h
  7. 25 80
      src/CodeGeneration.cpp
  8. 42 8
      src/CodegenVisitor.cpp
  9. 2 0
      src/CodegenVisitor.h
  10. 28 0
      src/Scope.cpp
  11. 16 0
      src/Scope.h
  12. 8 0
      src/Semantic.cpp
  13. 20 1
      src/Semantic.h
  14. 1 1
      src/Type.cpp
  15. 5 30
      src/lexer.l
  16. 1 1
      src/main.cpp
  17. 14 4
      src/parser.y
  18. 28 5
      src/test.qlw

+ 1 - 1
src/Ast.cpp

@@ -23,13 +23,13 @@ ACCEPT_DEFINITION(FeatureDeclaration, StructureVisitor)
 ACCEPT_DEFINITION(FieldDeclaration, StructureVisitor)
 ACCEPT_DEFINITION(MethodDefinition, StructureVisitor)
 ACCEPT_DEFINITION(VariableDeclaration, StructureVisitor)
-ACCEPT_DEFINITION(ArgumentDeclaration, StructureVisitor)
 
 ACCEPT_DEFINITION(DoEndBlock, StructureVisitor)
 ACCEPT_DEFINITION(Statement, StructureVisitor)
 ACCEPT_DEFINITION(Expression, StructureVisitor)
 ACCEPT_DEFINITION(FeatureCall, StructureVisitor)
 ACCEPT_DEFINITION(AssignmentStatement, StructureVisitor)
+ACCEPT_DEFINITION(ReturnStatement, StructureVisitor)
 ACCEPT_DEFINITION(NewVariableStatement, StructureVisitor)
 ACCEPT_DEFINITION(IntConst, StructureVisitor)
 ACCEPT_DEFINITION(UnaryOperation, StructureVisitor)

+ 17 - 1
src/Ast.h

@@ -58,6 +58,7 @@ namespace qlow
 
         struct FeatureCall;
         struct AssignmentStatement;
+        struct ReturnStatement;
         struct NewVariableStatement;
         struct IntConst;
 
@@ -192,7 +193,7 @@ struct qlow::ast::ArgumentDeclaration :
     {
     }
 
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
+    //virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
 };
 
 
@@ -256,6 +257,21 @@ struct qlow::ast::FeatureCall : public Expression, public Statement
 };
 
 
+struct qlow::ast::ReturnStatement : public Statement
+{
+    std::unique_ptr<Expression> expr;
+
+    inline ReturnStatement(std::unique_ptr<Expression>&& expr, const CodePosition& cp) :
+        AstObject{ cp },
+        Statement{ cp },
+        expr{ std::move(expr) }
+    {
+    }
+
+    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
+};
+
+
 struct qlow::ast::AssignmentStatement : public Statement
 {
     std::unique_ptr<Expression> target;

+ 35 - 7
src/AstVisitor.cpp

@@ -54,6 +54,21 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::MethodDefiniti
     auto m = std::make_unique<sem::Method>(scope, returnType.value());
     m->name = ast.name;
     m->astNode = &ast;
+    
+    for (auto& arg : ast.arguments) {
+        auto var = arg->accept(*this, scope);
+        if (dynamic_cast<sem::Variable*>(var.get())) {
+            std::unique_ptr<sem::Variable> variable =
+                unique_dynamic_cast<sem::Variable>(std::move(var));
+            m->arguments.push_back(variable.get());
+            std::string varname = variable->name;
+            m->scope.putVariable(varname, std::move(variable));
+        }
+        else {
+            throw "internal error creating argument";
+        }
+    }
+    
     return m;
     //throw "  std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::MethodDefinition& ast, sem::Scope& scope) shouldn't be called";
 }
@@ -77,12 +92,6 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::VariableDeclar
 }
 
 
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::ArgumentDeclaration& ast, sem::Scope& scope)
-{
-    throw "shouldn't be called";
-}
-
-
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::DoEndBlock& ast, sem::Scope& scope)
 {
     auto body = std::make_unique<sem::DoEndBlock>(scope);
@@ -101,7 +110,9 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::DoEndBlock& as
         
         auto v = statement->accept(*this, body->scope);
         if (dynamic_cast<sem::FeatureCallExpression*>(v.get()) != nullptr) {
-            body->statements.push_back(std::make_unique<sem::FeatureCallStatement>(unique_dynamic_cast<sem::FeatureCallExpression>(std::move(v))));
+            body->statements.push_back(
+                std::make_unique<sem::FeatureCallStatement>(
+                unique_dynamic_cast<sem::FeatureCallExpression>(std::move(v))));
         }
         else {
             body->statements.push_back(unique_dynamic_cast<sem::Statement>(std::move(v)));
@@ -137,6 +148,15 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureCall& a
     }
     else if (method) {
         auto fce = std::make_unique<sem::FeatureCallExpression>();
+        for (auto& arg : ast.arguments) {
+            auto argument = arg->accept(*this, scope);
+            if (dynamic_cast<sem::Expression*>(argument.get())) {
+                fce->arguments.push_back(unique_dynamic_cast<sem::Expression>(std::move(argument)));
+            }
+            else {
+                throw "internal error: non-expression passed as function parameter";
+            }
+        }
         fce->callee = method;
         return fce;
     }
@@ -162,6 +182,14 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::AssignmentStat
 }
 
 
+std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::ReturnStatement& ast, sem::Scope& scope)
+{
+    auto as = std::make_unique<sem::ReturnStatement>();
+    as->value = unique_dynamic_cast<sem::Expression>(ast.expr->accept(*this, scope));
+    return as;
+}
+
+
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::NewVariableStatement& ast, sem::Scope& scope)
 {
     throw "shouldn't be called";

+ 2 - 2
src/AstVisitor.h

@@ -63,12 +63,12 @@ class qlow::StructureVisitor :
         ast::FieldDeclaration,
         ast::MethodDefinition,
         ast::VariableDeclaration,
-        ast::ArgumentDeclaration,
         ast::DoEndBlock,
         ast::Statement,
         ast::Expression,
         ast::FeatureCall,
         ast::AssignmentStatement,
+        ast::ReturnStatement,
         ast::NewVariableStatement,
         ast::IntConst,
         ast::UnaryOperation,
@@ -83,12 +83,12 @@ public:
     ReturnType visit(ast::FieldDeclaration& ast, sem::Scope& scope) override;
     ReturnType visit(ast::MethodDefinition& ast, sem::Scope& scope) override;
     ReturnType visit(ast::VariableDeclaration& ast, sem::Scope& scope) override;
-    ReturnType visit(ast::ArgumentDeclaration& ast, sem::Scope& scope) override;
     ReturnType visit(ast::DoEndBlock& ast, sem::Scope& scope) override;
     ReturnType visit(ast::Statement& 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;
+    ReturnType visit(ast::ReturnStatement& ast, sem::Scope& scope) override;
     ReturnType visit(ast::NewVariableStatement& ast, sem::Scope& scope) override;
     ReturnType visit(ast::IntConst& ast, sem::Scope& scope) override;
     ReturnType visit(ast::UnaryOperation& ast, sem::Scope& scope) override;

+ 13 - 5
src/Builtin.cpp

@@ -1,16 +1,24 @@
 #include "Builtin.h"
+#include "Scope.h"
 
 using namespace qlow;
 
-sem::Class initInt32(void)
+sem::Class sem::int32 = sem::Class{ "Integer", sem::NativeScope::getInstance() };
+
+sem::NativeScope qlow::sem::generateNativeScope(void)
 {
-    sem::Class c{ nullptr, sem::nativeGlobalScope };
-    return c;
+    using sem::Class;
+    
+    sem::NativeScope scope;
+    
+    std::unique_ptr<sem::Type> int32 =
+        std::make_unique<sem::Type>(sem::Type::Kind::INTEGER, &sem::int32);
+    
+    scope.types.insert({"Integer", std::move(int32)});
+    return scope;
 }
 
 
-sem::GlobalScope sem::nativeGlobalScope{};
-sem::Class sem::Int32 = initInt32();
 
 
 

+ 2 - 3
src/Builtin.h

@@ -10,9 +10,8 @@ namespace qlow
 {
     namespace sem
     {
-        extern GlobalScope nativeGlobalScope;
-        extern Class Int32;
-        //extern Class String;
+        extern Class int32;
+        NativeScope generateNativeScope(void);
     }
 }
 

+ 25 - 80
src/CodeGeneration.cpp

@@ -53,43 +53,44 @@ std::unique_ptr<llvm::Module> generateModule(const sem::SymbolTable<sem::Class>&
         cl->llvmType = st;
     }
     
-    for (auto& [name, cl] : classes){
+    // create all llvm functions
+    for (auto& [name, cl] : classes) {
         for (auto& [name, method] : cl->methods) {
-            std::vector<Type*> doubles(1, Type::getDoubleTy(context));
+            std::vector<Type*> argumentTypes;
+            Type* returnType = method->returnType.getLlvmType(context);
+            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", name.c_str());
 #endif 
-            llvm::Type* returnType = method->returnType.getLlvmType(context);
             if (returnType == nullptr)
                 throw "invalid return type";
-            FunctionType* funcType = FunctionType::get(returnType, doubles, false);
             Function* func = Function::Create(funcType, Function::ExternalLinkage, method->name, module.get());
             method->llvmNode = func;
+            size_t index = 0;
+            for (auto& arg : func->args()) {
+                method->arguments[index]->allocaInst = &arg;
+#ifdef DEBUGGING
+                printf("allocaInst of arg '%s': %p\n", method->arguments[index]->name.c_str(), method->arguments[index]->allocaInst);
+#endif 
+                index++;
+            }
         }
     }
 
     for (auto& [name, cl] : classes){
         for (auto& [name, method] : cl->methods) {
-
             FunctionGenerator fg(*method, module.get());
-            fg.generate();
-
-            /*
-            FunctionType* funcType = FunctionType::get(Type::getDoubleTy(context), doubles, false);
-            Function* func = Function::Create(funcType, Function::ExternalLinkage, "qlow_function", module.get());
-            BasicBlock* bb = BasicBlock::Create(context, "entry", func);
-            IRBuilder<> builder(context);
-            builder.SetInsertPoint(bb);
-
-            Function::arg_iterator args = func->arg_begin();
-
-            Argument* arg = &(*args);
-            
-            Value* val = llvm::ConstantFP::get(context, llvm::APFloat(5.0));
-            Value* val2 = llvm::ConstantFP::get(context, llvm::APFloat(1.0));
-            Value* result = builder.CreateFAdd(arg, val2, "add_constants");
-            builder.CreateRet(result);
-            */
+            Function* f = fg.generate();
+            llvm::verifyFunction(*f, &llvm::errs());
+#ifdef DEBUGGING
+            printf("verified function: %s\n", method->name.c_str());
+#endif
         }
     }
     return module;
@@ -145,49 +146,6 @@ void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Modul
     dest.close();
 
     return;
-
-    //pm.add(createPrintModulePass(&outs()));
-    //pm.run(module);
-
-
-
-
-    /*
-    auto RM = llvm::Optional<llvm::Reloc::Model>();
-    auto targetMachine =
-        target->createTargetMachine(TargetTriple, CPU, Features, opt, RM);
-
-        */
-/*  TargetOptions opt;
-  auto RM = Optional<Reloc::Model>();
-  auto TheTargetMachine =
-      Target->createTargetMachine(TargetTriple, CPU, Features, opt, RM);
-
-  TheModule->setDataLayout(TheTargetMachine->createDataLayout());
-
-  auto Filename = "output.o";
-  std::error_code EC;
-  raw_fd_ostream dest(Filename, EC, sys::fs::F_None);
-
-  if (EC) {
-    errs() << "Could not open file: " << EC.message();
-    return 1;
-  }
-
-  legacy::PassManager pass;
-  auto FileType = TargetMachine::CGFT_ObjectFile;
-
-  if (TheTargetMachine->addPassesToEmitFile(pass, dest, llvm::LLVMTargetMachine::CGFT_ObjectFile, FileType)) {
-    errs() << "TheTargetMachine can't emit a file of this type";
-    return 1;
-  }
-
-  pass.run(*TheModule);
-  dest.flush();
-
-  outs() << "Wrote " << Filename << "\n";
-
-  return 0;*/
 }
 
 } // namespace gen
@@ -204,9 +162,6 @@ llvm::Function* qlow::gen::FunctionGenerator::generate(void)
     using llvm::Value;
     using llvm::IRBuilder;
 
-    std::vector<Type*> doubles(1, Type::getDoubleTy(context));
-    FunctionType* funcType = FunctionType::get(Type::getDoubleTy(context), doubles, false);
-    //Function* func = Function::Create(funcType, Function::ExternalLinkage, method.name, module);
     Function* func = module->getFunction(method.name);
 
     if (func == nullptr) {
@@ -214,23 +169,13 @@ llvm::Function* qlow::gen::FunctionGenerator::generate(void)
     }
 
     BasicBlock* bb = BasicBlock::Create(context, "entry", func);
-    
-    /*Function::arg_iterator args = func->arg_begin();
-
-    Argument* arg = &(*args);
-    
-    Value* val = llvm::ConstantFP::get(context, llvm::APFloat(5.0));
-    Value* val2 = llvm::ConstantFP::get(context, llvm::APFloat(1.0));
-    Value* result = builder.CreateFAdd(arg, val2, "add_constants");
-    builder.CreateRet(result);
-    */
 
     pushBlock(bb);
 
     IRBuilder<> builder(context);
     builder.SetInsertPoint(bb);
     for (auto& [name, var] : method.body->scope.getLocals()) {
-        llvm::AllocaInst* v = builder.CreateAlloca(Type::getDoubleTy(context));
+        llvm::AllocaInst* v = builder.CreateAlloca(var->type.getLlvmType(context));
         var->allocaInst = v;
     }
     

+ 42 - 8
src/CodegenVisitor.cpp

@@ -11,8 +11,14 @@ using namespace qlow;
 
 std::pair<llvm::Value*, sem::Type> ExpressionVisitor::visit(sem::LocalVariableExpression& lve, llvm::IRBuilder<>& builder)
 {
-    llvm::Value* val = builder.CreateLoad(lve.var->allocaInst);
-    return { val, lve.var->type };
+    assert(lve.var->allocaInst != nullptr);
+    if (dynamic_cast<llvm::AllocaInst*>(lve.var->allocaInst)) {
+        llvm::Value* val = builder.CreateLoad(lve.var->allocaInst);
+        return { val, lve.var->type };
+    }
+    else {
+        return { lve.var->allocaInst, lve.var->type };
+    }
 }
 
 
@@ -69,13 +75,25 @@ std::pair<llvm::Value*, sem::Type> ExpressionVisitor::visit(sem::FeatureCallExpr
 {
     using llvm::Value;
     std::vector<Value*> arguments;
-    for (auto& arg : call.arguments) {
+    if (call.arguments.size() != call.callee->arguments.size()) {
+        throw "wrong number of arguments";
+    }
+    for (size_t i = 0; i < call.arguments.size(); i++) {
+        // : call.arguments) {
+        auto& arg = call.arguments[i];
         auto [value, type] = arg->accept(*this, builder);
-        // TODO implement type check
+        
+        if (type != call.callee->arguments[i]->type) {
+            throw "argument type mismatch";
+        }
+        
         arguments.push_back(value);
     }
-    //return builder.CreateCall(nullptr, arguments);
-    return { nullptr, sem::Type::NULL_TYPE };
+    auto returnType = call.callee->returnType;
+    llvm::CallInst* callInst = builder.CreateCall(call.callee->llvmNode, arguments);
+    
+    return { callInst, returnType };
+    //return { nullptr, sem::Type::NULL_TYPE };
 }
 
 std::pair<llvm::Value*, sem::Type> ExpressionVisitor::visit(sem::IntConst& node, llvm::IRBuilder<>& builder)
@@ -93,8 +111,24 @@ llvm::Value* StatementVisitor::visit(sem::AssignmentStatement& assignment,
     llvm::IRBuilder<> builder(fg.getContext());
     builder.SetInsertPoint(fg.getCurrentBlock());
     auto [val, type] = assignment.value->accept(fg.expressionVisitor, builder);
-    //builder.CreateRet(val);
-    return llvm::ConstantFP::get(fg.getContext(), llvm::APFloat(5.0));
+    if (auto* targetVar =
+        dynamic_cast<sem::LocalVariableExpression*>(assignment.target.get()); targetVar) {
+        builder.CreateStore(val, targetVar->var->allocaInst);
+    }
+    else
+        throw "only local variables are assignable at the moment";
+    return llvm::ConstantFP::get(fg.getContext(), llvm::APFloat(5123.0));
+}
+
+
+llvm::Value* StatementVisitor::visit(sem::ReturnStatement& returnStatement,
+        qlow::gen::FunctionGenerator& fg)
+{
+    llvm::IRBuilder<> builder(fg.getContext());
+    builder.SetInsertPoint(fg.getCurrentBlock());
+    auto [val, type] = returnStatement.value->accept(fg.expressionVisitor, builder);
+    builder.CreateRet(val);
+    return val;
 }
 
 

+ 2 - 0
src/CodegenVisitor.h

@@ -57,11 +57,13 @@ class qlow::StatementVisitor :
         gen::FunctionGenerator,
 
         sem::AssignmentStatement,
+        sem::ReturnStatement,
         sem::FeatureCallStatement
     >
 {
 public:
     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;
 };
 

+ 28 - 0
src/Scope.cpp

@@ -1,5 +1,6 @@
 #include "Scope.h"
 #include "Semantic.h"
+#include "Builtin.h"
 
 using namespace qlow;
 
@@ -22,6 +23,11 @@ sem::Method* sem::GlobalScope::getMethod(const std::string& name)
 
 std::optional<sem::Type> sem::GlobalScope::getType(const std::string& name)
 {
+    auto native = NativeScope::getInstance().getType(name);
+    if (native) {
+        return native;
+    }
+    
     auto t = classes.find(name);
     if (t != classes.end())
         return std::make_optional(Type(t->second.get()));
@@ -47,6 +53,28 @@ std::string sem::GlobalScope::toString(void)
 }
 
 
+std::optional<sem::Type> sem::NativeScope::getType(const std::string& name)
+{
+    auto t = types.find(name);
+    if (t != types.end())
+        return *t->second;
+    return std::nullopt;
+}
+
+
+sem::NativeScope sem::NativeScope::instance = sem::generateNativeScope();
+sem::NativeScope& sem::NativeScope::getInstance(void)
+{
+    return instance;
+}
+
+
+std::string sem::NativeScope::toString(void)
+{
+    return "NativeScope";
+}
+
+
 sem::Variable* sem::ClassScope::getVariable(const std::string& name)
 {
     if (class_ref == nullptr)

+ 16 - 0
src/Scope.h

@@ -24,6 +24,7 @@ namespace qlow
 
         class Scope;
         class GlobalScope;
+        class NativeScope;
         class ClassScope;
         class LocalScope;
     }
@@ -57,6 +58,21 @@ public:
 };
 
 
+class qlow::sem::NativeScope : public GlobalScope
+{
+    static NativeScope instance;
+public:
+    SymbolTable<Type> types;
+public:
+    virtual std::optional<Type> getType(const std::string& name);
+
+    virtual std::string toString(void);
+    
+    static NativeScope& getInstance(void);
+};
+
+
+
 class qlow::sem::ClassScope : public Scope
 {
     Scope& parentScope;

+ 8 - 0
src/Semantic.cpp

@@ -146,6 +146,7 @@ ACCEPT_DEFINITION(FeatureCallExpression, ExpressionVisitor, std::pair<llvm::Valu
 ACCEPT_DEFINITION(IntConst, ExpressionVisitor, std::pair<llvm::Value* COMMA Type>, llvm::IRBuilder<>&)
 
 ACCEPT_DEFINITION(AssignmentStatement, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&) 
+ACCEPT_DEFINITION(ReturnStatement, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&) 
 ACCEPT_DEFINITION(FeatureCallStatement, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&) 
 
 std::string AssignmentStatement::toString(void) const
@@ -155,11 +156,18 @@ std::string AssignmentStatement::toString(void) const
 }
 
 
+std::string ReturnStatement::toString(void) const
+{
+    return "ReturnStatement[" + this->value->toString() + "]";
+}
+
+
 std::string LocalVariableExpression::toString(void) const
 {
     return "LocalVariableExpression[" + var->name + "]";
 }
 
+
 std::string BinaryOperation::toString(void) const
 {
     return "BinaryOperation[" + left->toString() + ", " +

+ 20 - 1
src/Semantic.h

@@ -33,6 +33,7 @@ namespace qlow
 
         struct FeatureCallStatement;
         struct AssignmentStatement;
+        struct ReturnStatement;
         
         struct LocalVariableExpression;
 
@@ -85,6 +86,14 @@ struct qlow::sem::Class : public SemanticObject
         llvmType{ nullptr }
     {
     }
+
+    inline Class(const std::string& nativeName, GlobalScope& globalScope) :
+        astNode{ nullptr },
+        name{ nativeName },
+        scope{ globalScope, this },
+        llvmType{ nullptr }
+    {
+    }
     
     virtual std::string toString(void) const override;
 };
@@ -97,7 +106,7 @@ struct qlow::sem::Variable : public SemanticObject
 
     /// if this is a local variable, this stores a reference to the llvm
     /// instance of this variable.
-    llvm::AllocaInst* allocaInst;
+    llvm::Value* allocaInst;
     
     Variable(void) = default;
     inline Variable(Type type, std::string& name) :
@@ -120,6 +129,7 @@ struct qlow::sem::Method : public SemanticObject
 {
     Class* containingType;
     Type returnType;
+    std::vector<Variable*> arguments;
     std::string name;
     ast::MethodDefinition* astNode;
     std::unique_ptr<DoEndBlock> body;
@@ -161,6 +171,15 @@ struct qlow::sem::AssignmentStatement : public Statement
 };
 
 
+struct qlow::sem::ReturnStatement : public Statement 
+{
+    std::unique_ptr<Expression> value;
+
+    virtual std::string toString(void) const override;
+    virtual llvm::Value* accept(qlow::StatementVisitor&, gen::FunctionGenerator&) override;
+};
+
+
 struct qlow::sem::Expression :
     public SemanticObject,
     public Visitable<std::pair<llvm::Value*, sem::Type>,

+ 1 - 1
src/Type.cpp

@@ -76,6 +76,6 @@ bool sem::Type::operator != (const Type& other) const
 
 
 const sem::Type sem::Type::NULL_TYPE = sem::Type{ sem::Type::Kind::NULL_TYPE };
-const sem::Type sem::Type::INTEGER = sem::Type{ sem::Type::Kind::INTEGER, &sem::Int32 };
+const sem::Type sem::Type::INTEGER = sem::Type{ sem::Type::Kind::INTEGER, &sem::int32 };
 
 

+ 5 - 30
src/lexer.l

@@ -66,15 +66,15 @@ extern QLOW_PARSER_LTYPE qlow_parser_lloc;
 <COMMENT>\n             ;
 <COMMENT>.              ; // inside comment, ignore everything
 
-<LINE_COMMENT>\n        yy_push_state(INITIAL);
+<LINE_COMMENT>\n        yy_pop_state(); //yy_push_state(INITIAL);
 <LINE_COMMENT>.         ; // inside comment, ignore everything
 
 <STRING>"\""            yy_pop_state();
 <STRING>[^\"^]*         printf("%s\n", std::string(yytext, yyleng).c_str());
 
-<INITIAL>"/*"           yy_push_state(COMMENT); commentDepth = 1;
-<INITIAL>"//"           yy_push_state(LINE_COMMENT);
-<INITIAL>"\""           yy_push_state(STRING);
+"/*"                    yy_push_state(COMMENT); commentDepth = 1;
+"//"                    yy_push_state(LINE_COMMENT);
+"\""                    yy_push_state(STRING);
 
 
 [\t ]                   ; // Space or tab ignored
@@ -86,6 +86,7 @@ extern QLOW_PARSER_LTYPE qlow_parser_lloc;
 <METHOD>"end"           yy_pop_state(); return SET_TOKEN(END);
 <INITIAL>"end"          return SET_TOKEN(END);
 "if"                    return SET_TOKEN(IF);
+"return"                return SET_TOKEN(RETURN);
 
 ":"                     return SET_TOKEN(COLON);
 ";"                     return SET_TOKEN(SEMICOLON);
@@ -108,29 +109,3 @@ extern QLOW_PARSER_LTYPE qlow_parser_lloc;
 .                       printf("Unexpected symbol %s.\n", std::string(yytext, yyleng).c_str()); yyterminate();
 
 %%
-
-
-/*
-
-[\t ]                   ; // Space or tab ignored
-\/\*[.\n]*\*\/          ; // comment
-\n                      return SET_TOKEN(NEW_LINE);
-
-":"                     return SET_TOKEN(COLON);
-","                     return SET_TOKEN(COMMA);
-":="                    return SET_TOKEN(ASSIGN);
-"."                     return SET_TOKEN(DOT);
-
-"+"		        return SET_TOKEN(PLUS);
-"-"		        return SET_TOKEN(MINUS);
-"*"		        return SET_TOKEN(ASTERISK);
-"/"		        return SET_TOKEN(SLASH);
-
-"("                     return SET_TOKEN(ROUND_LEFT);
-")"                     return SET_TOKEN(ROUND_RIGHT);
-
-"class"                 return SET_TOKEN(CLASS);
-"do"                    return SET_TOKEN(DO);
-"end"                   return SET_TOKEN(END);
-"if"                    return SET_TOKEN(IF);
-*/

+ 1 - 1
src/main.cpp

@@ -57,7 +57,7 @@ int main(int argc, char** argv)
         auto mainmain = mainClass->methods.find("main");
         qlow::sem::Method* mainMethod = nullptr;
         if (mainmain == mainClass->methods.end()) {
-            throw "No main method found inside Main class!";
+            //throw "No main method found inside Main class!";
         }
         else {
             mainMethod = mainmain->second.get();

+ 14 - 4
src/parser.y

@@ -74,6 +74,7 @@ std::unique_ptr<ClassList> parsedClasses;
 
     qlow::ast::FeatureCall* featureCall;
     qlow::ast::AssignmentStatement* assignmentStatement;
+    qlow::ast::ReturnStatement* returnStatement;
     qlow::ast::NewVariableStatement* newVariableStatement;
 
     qlow::ast::UnaryOperation* unaryOperation;
@@ -87,7 +88,7 @@ std::unique_ptr<ClassList> parsedClasses;
 
 %token <string> IDENTIFIER
 %token <string> INT_LITERAL
-%token <token> CLASS DO END IF
+%token <token> CLASS DO END IF RETURN
 %token <token> NEW_LINE
 %token <token> SEMICOLON COLON COMMA DOT ASSIGN OPERATOR
 %token <token> ROUND_LEFT ROUND_RIGHT
@@ -106,6 +107,7 @@ std::unique_ptr<ClassList> parsedClasses;
 %type <op> operator
 %type <featureCall> featureCall
 %type <assignmentStatement> assignmentStatement 
+%type <returnStatement> returnStatement 
 %type <newVariableStatement> newVariableStatement
 %type <unaryOperation> unaryOperation
 %type <binaryOperation> binaryOperation
@@ -218,7 +220,7 @@ statements:
         $$ = new std::vector<std::unique_ptr<Statement>>();
     }
     |
-    statements statement pnl {
+    statements statement {
         $$ = $1;
         $$->push_back(std::unique_ptr<Statement>($2));
     };
@@ -243,14 +245,18 @@ statement:
         $$ = $1;
     }
     |
+    returnStatement statementEnd {
+        $$ = $1;
+    }
+    |
     newVariableStatement statementEnd {
         $$ = $1;
     };
     
 statementEnd:
-    SEMICOLON {}
+    SEMICOLON pnl {}
     |
-    NEW_LINE {}
+    NEW_LINE pnl {}
     ;
 
 
@@ -359,6 +365,10 @@ assignmentStatement:
         $$ = new AssignmentStatement(std::unique_ptr<Expression>($1), std::unique_ptr<Expression>($3), @$);
     };
 
+returnStatement:
+    RETURN expression {
+        $$ = new ReturnStatement(std::unique_ptr<Expression>($2), @$);
+    };
 
 newVariableStatement:
     IDENTIFIER COLON IDENTIFIER {

+ 28 - 5
src/test.qlw

@@ -3,33 +3,56 @@
 class Main
     hoi: Fudi 
     fop: FF do
-        var: Integer;
+        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
 
-    main: Integer do
+    mainn: Integer do
         fop
+        return 12
     end
 end
 
+
 class FF
+    field1: Integer
+    field2: Integer
+
+    calc: Integer do
+        return 100000
+    end
+
+    verdoppel(x: Integer): Integer do
+        return x + x
+    end
+
     sum_func: Integer do
-        variable: Integer;
+        variable: Integer
+        variable2: FF
+        variable := verdoppel(51)
+        return variable2.field1
     end
 end
 
+
 class Fudi
 end
 
-class Integer               end
-