Nicolas Winkler пре 6 година
родитељ
комит
952f476849
14 измењених фајлова са 157 додато и 36 уклоњено
  1. 2 1
      src/Ast.cpp
  2. 21 16
      src/Ast.h
  3. 10 4
      src/AstVisitor.cpp
  4. 4 2
      src/AstVisitor.h
  5. 10 0
      src/CodeGeneration.cpp
  6. 42 0
      src/CodegenVisitor.cpp
  7. 4 0
      src/CodegenVisitor.h
  8. 2 0
      src/Semantic.cpp
  9. 25 4
      src/Semantic.h
  10. 3 1
      src/Util.h
  11. 1 0
      src/lexer.l
  12. 9 0
      src/main.cpp
  13. 18 6
      src/parser.y
  14. 6 2
      src/test.qlw

+ 2 - 1
src/Ast.cpp

@@ -24,8 +24,9 @@ ACCEPT_DEFINITION(FieldDeclaration, StructureVisitor)
 ACCEPT_DEFINITION(MethodDefinition, StructureVisitor)
 ACCEPT_DEFINITION(VariableDeclaration, StructureVisitor)
 
-ACCEPT_DEFINITION(DoEndBlock, StructureVisitor)
 ACCEPT_DEFINITION(Statement, StructureVisitor)
+ACCEPT_DEFINITION(DoEndBlock, StructureVisitor)
+ACCEPT_DEFINITION(IfElseBlock, StructureVisitor)
 ACCEPT_DEFINITION(Expression, StructureVisitor)
 ACCEPT_DEFINITION(FeatureCall, StructureVisitor)
 ACCEPT_DEFINITION(AssignmentStatement, StructureVisitor)

+ 21 - 16
src/Ast.h

@@ -51,11 +51,11 @@ namespace qlow
         struct VariableDeclaration;
         struct ArgumentDeclaration;
 
+        struct Statement;
+        
         struct DoEndBlock;
-
         struct IfElseBlock;
 
-        struct Statement;
         struct Expression;
 
         struct FeatureCall;
@@ -199,12 +199,24 @@ struct qlow::ast::ArgumentDeclaration :
 };
 
 
-struct qlow::ast::DoEndBlock : public AstObject
+struct qlow::ast::Statement : public virtual AstObject
+{
+    inline Statement(const CodePosition& cp) :
+        AstObject{ cp } {}
+        
+    virtual ~Statement(void);
+
+    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
+};
+
+
+struct qlow::ast::DoEndBlock : public Statement 
 {
     OwningList<Statement> statements;
     
     inline DoEndBlock(OwningList<Statement>&& statements, const CodePosition& cp) :
         AstObject{ cp },
+        Statement{ cp },
         statements(std::move(statements))
     {
     }
@@ -213,15 +225,19 @@ struct qlow::ast::DoEndBlock : public AstObject
 };
 
 
-struct qlow::ast::IfElseBlock : public AstObject
+struct qlow::ast::IfElseBlock : public Statement
 {
+    std::unique_ptr<Expression> condition;
     std::unique_ptr<DoEndBlock> ifBlock;
     std::unique_ptr<DoEndBlock> elseBlock;
     
-    inline IfElseBlock(std::unique_ptr<DoEndBlock> ifBlock,
+    inline IfElseBlock(std::unique_ptr<Expression> condition,
+                       std::unique_ptr<DoEndBlock> ifBlock,
                        std::unique_ptr<DoEndBlock> elseBlock,
                        const CodePosition& cp) :
         AstObject{ cp },
+        Statement{ cp },
+        condition{ std::move(condition) },
         ifBlock{ std::move(ifBlock) },
         elseBlock{ std::move(elseBlock) }
     {
@@ -231,17 +247,6 @@ struct qlow::ast::IfElseBlock : public AstObject
 };
 
 
-struct qlow::ast::Statement : public virtual AstObject
-{
-    inline Statement(const CodePosition& cp) :
-        AstObject{ cp } {}
-        
-    virtual ~Statement(void);
-
-    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
-};
-
-
 struct qlow::ast::Expression : public virtual AstObject
 {
     inline Expression(const CodePosition& cp) :

+ 10 - 4
src/AstVisitor.cpp

@@ -92,6 +92,14 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::VariableDeclar
 }
 
 
+std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::Statement& ast, sem::Scope& scope)
+{
+    printf("at: %d:%d to %d:%d\n", ast.pos.first_line, ast.pos.first_column, ast.pos.last_line, ast.pos.last_column);
+    printf("type: %s\n", typeid(ast).name());
+    throw "visit(Statement) 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);
@@ -122,11 +130,9 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::DoEndBlock& as
 }
 
 
-std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::Statement& ast, sem::Scope& scope)
+std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::IfElseBlock& ast, sem::Scope& scope)
 {
-    printf("at: %d:%d to %d:%d\n", ast.pos.first_line, ast.pos.first_column, ast.pos.last_line, ast.pos.last_column);
-    printf("type: %s\n", typeid(ast).name());
-    throw "visit(Statement) shouldn't be called";
+    
 }
 
 

+ 4 - 2
src/AstVisitor.h

@@ -63,8 +63,9 @@ class qlow::StructureVisitor :
         ast::FieldDeclaration,
         ast::MethodDefinition,
         ast::VariableDeclaration,
-        ast::DoEndBlock,
         ast::Statement,
+        ast::DoEndBlock,
+        ast::IfElseBlock,
         ast::Expression,
         ast::FeatureCall,
         ast::AssignmentStatement,
@@ -83,8 +84,9 @@ 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::DoEndBlock& ast, sem::Scope& scope) override;
     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::Expression& ast, sem::Scope& scope) override;
     ReturnType visit(ast::FeatureCall& ast, sem::Scope& scope) override;
     ReturnType visit(ast::AssignmentStatement& ast, sem::Scope& scope) override;

+ 10 - 0
src/CodeGeneration.cpp

@@ -33,6 +33,10 @@ std::unique_ptr<llvm::Module> generateModule(const sem::SymbolTable<sem::Class>&
     using llvm::BasicBlock;
     using llvm::Value;
     using llvm::IRBuilder;
+    
+#ifdef DEBUGGING
+        printf("creating llvm module\n"); 
+#endif 
 
     std::unique_ptr<Module> module = llvm::make_unique<Module>("qlow_module", context);
 
@@ -161,6 +165,10 @@ llvm::Function* qlow::gen::FunctionGenerator::generate(void)
     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);
 
@@ -175,6 +183,8 @@ llvm::Function* qlow::gen::FunctionGenerator::generate(void)
     IRBuilder<> builder(context);
     builder.SetInsertPoint(bb);
     for (auto& [name, var] : method.body->scope.getLocals()) {
+        if (var.get() == nullptr)
+            throw "wtf null variable";
         llvm::AllocaInst* v = builder.CreateAlloca(var->type.getLlvmType(context));
         var->allocaInst = v;
     }

+ 42 - 0
src/CodegenVisitor.cpp

@@ -105,6 +105,48 @@ std::pair<llvm::Value*, sem::Type> ExpressionVisitor::visit(sem::IntConst& node,
 }
 
 
+llvm::Value* StatementVisitor::visit(sem::DoEndBlock& assignment,
+        qlow::gen::FunctionGenerator& fg)
+{
+    for (auto& statement : assignment.statements) {
+        statement->accept(*this, fg);
+    }
+    return nullptr;
+}
+
+
+llvm::Value* StatementVisitor::visit(sem::IfElseBlock& ifElseBlock,
+        qlow::gen::FunctionGenerator& fg)
+{
+    using llvm::Value;
+    using llvm::BasicBlock;
+    
+    llvm::IRBuilder<> builder(fg.getContext());
+    builder.SetInsertPoint(fg.getCurrentBlock());
+    auto [condition, condType] = ifElseBlock.condition->accept(fg.expressionVisitor, builder);
+    
+    llvm::Function* function = fg.getCurrentBlock()->getParent();
+    
+    BasicBlock* thenB = BasicBlock::Create(fg.getContext(), "then", function);
+    BasicBlock* elseB = BasicBlock::Create(fg.getContext(), "else");
+    BasicBlock* merge = BasicBlock::Create(fg.getContext(), "merge");
+    
+    fg.pushBlock(thenB);
+    ifElseBlock.ifBlock->accept(*this, fg);
+    builder.SetInsertPoint(thenB);
+    builder.CreateBr(merge);
+    fg.popBlock();
+    fg.pushBlock(elseB);
+    ifElseBlock.elseBlock->accept(*this, fg);
+    builder.SetInsertPoint(elseB);
+    builder.CreateBr(merge);
+    fg.popBlock();
+    
+    builder.CreateCondBr(condition, thenB, elseB); 
+    fg.pushBlock(merge);
+}
+
+
 llvm::Value* StatementVisitor::visit(sem::AssignmentStatement& assignment,
         qlow::gen::FunctionGenerator& fg)
 {

+ 4 - 0
src/CodegenVisitor.h

@@ -56,12 +56,16 @@ class qlow::StatementVisitor :
         llvm::Value*,
         gen::FunctionGenerator,
 
+        sem::DoEndBlock,
+        sem::IfElseBlock,
         sem::AssignmentStatement,
         sem::ReturnStatement,
         sem::FeatureCallStatement
     >
 {
 public:
+    llvm::Value* visit(sem::DoEndBlock& node, gen::FunctionGenerator&) override;
+    llvm::Value* visit(sem::IfElseBlock& 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;

+ 2 - 0
src/Semantic.cpp

@@ -146,6 +146,8 @@ 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(DoEndBlock, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&) 
+ACCEPT_DEFINITION(IfElseBlock, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&) 
 ACCEPT_DEFINITION(ReturnStatement, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&) 
 ACCEPT_DEFINITION(FeatureCallStatement, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&) 
 

+ 25 - 4
src/Semantic.h

@@ -27,10 +27,11 @@ namespace qlow
         struct Field;
         struct Method;
 
-        struct DoEndBlock;
         struct Statement;
         struct Expression;
 
+        struct DoEndBlock;
+        struct IfElseBlock;
         struct FeatureCallStatement;
         struct AssignmentStatement;
         struct ReturnStatement;
@@ -145,19 +146,39 @@ struct qlow::sem::Method : public SemanticObject
 };
 
 
-struct qlow::sem::DoEndBlock : public SemanticObject
+struct qlow::sem::Statement : public SemanticObject, public Visitable<llvm::Value*, gen::FunctionGenerator, qlow::StatementVisitor>
+{
+    virtual llvm::Value* accept(qlow::StatementVisitor&, gen::FunctionGenerator&) = 0;
+};
+
+
+struct qlow::sem::DoEndBlock : public Statement
 {
     LocalScope scope;
     OwningList<Statement> statements;
 
     inline DoEndBlock(Scope& parentScope) :
         scope{ parentScope } {}
+    
+    virtual llvm::Value* accept(qlow::StatementVisitor&, gen::FunctionGenerator&) override;
 };
 
 
-struct qlow::sem::Statement : public SemanticObject, public Visitable<llvm::Value*, gen::FunctionGenerator, qlow::StatementVisitor>
+struct qlow::sem::IfElseBlock : public Statement
 {
-    virtual llvm::Value* accept(qlow::StatementVisitor&, gen::FunctionGenerator&) = 0;
+    std::unique_ptr<Expression> condition;
+    std::unique_ptr<DoEndBlock> ifBlock;
+    std::unique_ptr<DoEndBlock> elseBlock;
+    inline IfElseBlock(std::unique_ptr<Expression> condition,
+                       std::unique_ptr<DoEndBlock> ifBlock,
+                       std::unique_ptr<DoEndBlock> elseBlock) :
+        condition{ std::move(condition) },
+        ifBlock{ std::move(ifBlock) },
+        elseBlock{ std::move(elseBlock) }
+    {
+    }
+    
+    virtual llvm::Value* accept(qlow::StatementVisitor&, gen::FunctionGenerator&) override;
 };
 
 

+ 3 - 1
src/Util.h

@@ -4,6 +4,7 @@
 #include <vector>
 #include <memory>
 #include <sstream>
+//#include <typeinfo>
 
 
 namespace qlow
@@ -27,7 +28,8 @@ namespace qlow
             return std::unique_ptr<T> (casted);
         else {
             delete released;
-            throw "invalid unique_dynamic_cast";
+            throw "failed unique dynamic cast";
+            //throw std::string("invalid unique_dynamic_cast to ") + typeid(T).name();
         }
     }
 

+ 1 - 0
src/lexer.l

@@ -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);
+"else"                  return SET_TOKEN(ELSE);
 "return"                return SET_TOKEN(RETURN);
 
 ":"                     return SET_TOKEN(COLON);

+ 9 - 0
src/main.cpp

@@ -62,20 +62,29 @@ int main(int argc, char** argv)
         else {
             mainMethod = mainmain->second.get();
         }
+        
+        std::cout << "starting code generation!" << std::endl;
 
         auto mod = qlow::gen::generateModule(semClasses->classes);
         qlow::gen::generateObjectFile("obj.o", std::move(mod));
+        
+        std::cout << "object exported!" << std::endl;
     }
     catch (qlow::sem::SemanticException& se)
     {
         std::cerr << se.getMessage() << std::endl;
     }
+    catch (const std::string& err)
+    {
+        std::cerr << err << std::endl;
+    }
     catch (const char* err)
     {
         std::cerr << err << std::endl;
     }
     catch (...)
     {
+        std::cerr << "an unknown error occurred" << std::endl;
     }
     
     if (::qlow_parser_in != stdin)

+ 18 - 6
src/parser.y

@@ -66,7 +66,7 @@ std::unique_ptr<ClassList> parsedClasses;
     std::vector<std::unique_ptr<qlow::ast::Expression>>* expressionList;
     qlow::ast::ArgumentDeclaration* argumentDeclaration;
     qlow::ast::DoEndBlock* doEndBlock;    
-    qlow::ast::ifElseBlock* ifElseBlock;    
+    qlow::ast::IfElseBlock* ifElseBlock;    
     qlow::ast::Statement* statement;
     qlow::ast::Expression* expression;
     qlow::ast::Operation::Operator op;
@@ -219,12 +219,19 @@ doEndBlock:
     
 ifElseBlock:
     IF expression doEndBlock {
-        $$ = new IfElseBlock($3, new DoEndBlock(@$), @$);
-        $2 = nullptr;
+        $$ = new IfElseBlock(std::unique_ptr<Expression>($2),
+                             std::unique_ptr<DoEndBlock>($3),
+                             std::unique_ptr<DoEndBlock>(nullptr), @$);
+        $2 = nullptr; $3 = nullptr;
     }
     |
-    IF DO statements ELSE statements END {
-    
+    IF expression DO statements ELSE statements END {
+        $$ = new IfElseBlock(std::unique_ptr<Expression>($2),
+                             std::make_unique<DoEndBlock>(std::move(*$4), @$),
+                             std::make_unique<DoEndBlock>(std::move(*$6), @$), @$);
+        $2 = nullptr;
+        delete $4;
+        delete $6;
     };
 
 
@@ -264,7 +271,12 @@ statement:
     |
     newVariableStatement statementEnd {
         $$ = $1;
-    };
+    }
+    |
+    ifElseBlock statementEnd {
+        $$ = $1;
+    }
+    ;
     
 statementEnd:
     SEMICOLON pnl {}

+ 6 - 2
src/test.qlw

@@ -43,9 +43,13 @@ class FF
 
     sum_func: Integer do
         variable: Integer
-        variable2: FF
         variable := verdoppel(51)
-        return variable
+        if variable do
+            variable := 1
+        else
+            variable := 2
+        end
+        return variable + 2
     end
 end