Browse Source

working on operators and casts

Nicolas Winkler 6 years ago
parent
commit
9a163bbf1d

+ 1 - 1
src/Ast.cpp

@@ -37,7 +37,7 @@ ACCEPT_DEFINITION(IntConst, StructureVisitor)
 ACCEPT_DEFINITION(UnaryOperation, StructureVisitor)
 ACCEPT_DEFINITION(UnaryOperation, StructureVisitor)
 ACCEPT_DEFINITION(BinaryOperation, StructureVisitor)
 ACCEPT_DEFINITION(BinaryOperation, StructureVisitor)
 ACCEPT_DEFINITION(NewArrayExpression, StructureVisitor)
 ACCEPT_DEFINITION(NewArrayExpression, StructureVisitor)
-
+ACCEPT_DEFINITION(CastExpression, StructureVisitor)
 
 
 
 
 Statement::~Statement(void)
 Statement::~Statement(void)

+ 39 - 7
src/Ast.h

@@ -75,6 +75,8 @@ namespace qlow
         struct BinaryOperation;
         struct BinaryOperation;
         
         
         struct NewArrayExpression;
         struct NewArrayExpression;
+        
+        struct CastExpression;
     }
     }
 
 
     namespace sem
     namespace sem
@@ -431,11 +433,14 @@ struct qlow::ast::IntConst : public Expression
 struct qlow::ast::Operation : public Expression
 struct qlow::ast::Operation : public Expression
 {
 {
     std::string opString;
     std::string opString;
+    CodePosition opPos;
 
 
-    inline Operation(const std::string& opString, const CodePosition& cp) :
+    inline Operation(const std::string& opString, const CodePosition& cp,
+                     const CodePosition& opPos) :
         AstObject{ cp },
         AstObject{ cp },
         Expression{ cp },
         Expression{ cp },
-        opString{ opString }
+        opString{ opString },
+        opPos{ opPos }
     {
     {
     }
     }
 };
 };
@@ -453,9 +458,11 @@ struct qlow::ast::UnaryOperation : public Operation
     std::unique_ptr<Expression> expr;
     std::unique_ptr<Expression> expr;
 
 
     inline UnaryOperation(std::unique_ptr<Expression> expr, Side side,
     inline UnaryOperation(std::unique_ptr<Expression> expr, Side side,
-                          const std::string& op, const CodePosition& cp) :
+                          const std::string& op, const CodePosition& cp,
+                          const CodePosition& opPos
+                         ) :
         AstObject{ cp },
         AstObject{ cp },
-        Operation{ op, cp },
+        Operation{ op, cp, opPos },
         side{ side },
         side{ side },
         expr{ std::move(expr) }
         expr{ std::move(expr) }
     {
     {
@@ -470,10 +477,16 @@ struct qlow::ast::BinaryOperation : public Operation
     std::unique_ptr<Expression> left;
     std::unique_ptr<Expression> left;
     std::unique_ptr<Expression> right;
     std::unique_ptr<Expression> right;
 
 
-    inline BinaryOperation(std::unique_ptr<Expression> left, std::unique_ptr<Expression> right, const std::string& op, const CodePosition& cp) :
+    inline BinaryOperation(std::unique_ptr<Expression> left,
+                           std::unique_ptr<Expression> right,
+                           const std::string& op,
+                           const CodePosition& cp,
+                           const CodePosition& opPos
+                          ) :
         AstObject{ cp },
         AstObject{ cp },
-        Operation{ op, cp },
-        left(std::move(left)), right(std::move(right))
+        Operation{ op, cp, opPos },
+        left{ std::move(left) },
+        right{ std::move(right) }
     {
     {
     }
     }
 
 
@@ -499,6 +512,25 @@ struct qlow::ast::NewArrayExpression : public Expression
 };
 };
 
 
 
 
+struct qlow::ast::CastExpression : public Expression
+{
+    std::unique_ptr<ast::Expression> expression;
+    std::unique_ptr<ast::Type> targetType;
+    
+    inline CastExpression(std::unique_ptr<ast::Expression> expression,
+                          std::unique_ptr<ast::Type> targetType,
+                          const CodePosition& cp) :
+        AstObject{ cp },
+        Expression{ cp },
+        expression{ std::move(expression) },
+        targetType{ std::move(targetType) }
+    {
+    }
+    
+    virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
+};
+
+
 #endif // QLOW_AST_H
 #endif // QLOW_AST_H
 
 
 
 

+ 73 - 9
src/AstVisitor.cpp

@@ -179,19 +179,64 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::Expression& as
 
 
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureCall& ast, sem::Scope& scope)
 std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::FeatureCall& ast, sem::Scope& scope)
 {
 {
-    std::unique_ptr<sem::SemanticObject> target = nullptr;
+    std::unique_ptr<sem::Expression> target = nullptr;
     if (ast.target) {
     if (ast.target) {
-        target = ast.target->accept(*this, scope);
+        target = unique_dynamic_cast<sem::Expression>(
+            ast.target->accept(*this, scope));
     }
     }
     
     
-    auto* method = scope.getMethod(ast.name);
-    auto* var = scope.getVariable(ast.name);
+    sem::Method* method;
+    sem::Variable* var;
     
     
-    if (var) {
+    if (target) {
+        method = target->type->getScope().getMethod(ast.name);
+        var = target->type->getScope().getVariable(ast.name);
+    }
+    else {
+        method = scope.getMethod(ast.name);
+        var = scope.getVariable(ast.name);
+    }
+    
+    if (target) {
+        if (var) {
+        }
+        else if (method) {
+            auto fce = std::make_unique<sem::FeatureCallExpression>(
+                std::move(target), method);
+    
+            if (ast.arguments.size() != method->arguments.size())
+                throw SemanticError(SemanticError::WRONG_NUMBER_OF_ARGUMENTS, ast.name, ast.pos);
+            for (size_t i = 0; i < ast.arguments.size(); i++) {
+                auto& arg = ast.arguments[i];
+                auto& argTypeShouldHave = method->arguments[i]->type;
+                auto argument = arg->accept(*this, scope);
+                if (sem::Expression* expr =
+                        dynamic_cast<sem::Expression*>(argument.get()); expr) {
+                    if (!expr->type->equals(*argTypeShouldHave))
+                        throw SemanticError(SemanticError::TYPE_MISMATCH,
+                            "argument passed to function has wrong type: '" +
+                            expr->type->asString() + "' instead of '" +
+                            argTypeShouldHave->asString() + "'",
+                            arg->pos
+                        );
+                    fce->arguments.push_back(
+                        unique_dynamic_cast<sem::Expression>(std::move(argument)));
+                }
+                else {
+                    throw "internal error: non-expression passed as function parameter";
+                }
+            }
+            return fce;
+        }
+        else {
+            throw SemanticError(SemanticError::FEATURE_NOT_FOUND, ast.name, ast.pos);
+        }
+    }
+    else if (var) {
         return std::make_unique<sem::LocalVariableExpression>(var);
         return std::make_unique<sem::LocalVariableExpression>(var);
     }
     }
     else if (method) {
     else if (method) {
-        auto fce = std::make_unique<sem::FeatureCallExpression>(method->returnType);
+        auto fce = std::make_unique<sem::FeatureCallExpression>(nullptr, method);
         for (auto& arg : ast.arguments) {
         for (auto& arg : ast.arguments) {
             auto argument = arg->accept(*this, scope);
             auto argument = arg->accept(*this, scope);
             if (dynamic_cast<sem::Expression*>(argument.get())) {
             if (dynamic_cast<sem::Expression*>(argument.get())) {
@@ -251,7 +296,7 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::UnaryOperation
     auto argument = unique_dynamic_cast<sem::Expression>(ast.expr->accept(*this, 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>(argument->type);
             // TODO not a feasible assumption
             // TODO not a feasible assumption
-    ret->op = ast.op;
+    ret->opString = ast.opString;
     ret->side = ast.side;
     ret->side = ast.side;
     ret->arg = std::move(argument);
     ret->arg = std::move(argument);
     return ret;
     return ret;
@@ -264,12 +309,22 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::BinaryOperatio
     auto rightEval = unique_dynamic_cast<sem::Expression>(ast.right->accept(*this, scope));
     auto rightEval = unique_dynamic_cast<sem::Expression>(ast.right->accept(*this, scope));
     
     
     sem::Method* operationMethod = leftEval->type->getScope().resolveMethod(
     sem::Method* operationMethod = leftEval->type->getScope().resolveMethod(
-        "+", {}
+        ast.opString, { rightEval->type }
     );
     );
     
     
+    Logger::getInstance().debug() << "looked for operation method for operator " <<
+    ast.opString << std::endl;
+    if (!operationMethod) {
+        throw SemanticError(SemanticError::OPERATOR_NOT_FOUND,
+            std::string("operator ") + ast.opString + " not found for types '" +
+            leftEval->type->asString() + "' and '" + rightEval->type->asString() + "'",
+            ast.opPos);
+    }
+    
     auto ret = std::make_unique<sem::BinaryOperation>(leftEval->type, &ast);
     auto ret = std::make_unique<sem::BinaryOperation>(leftEval->type, &ast);
     
     
-    ret->op = ast.op;
+    ret->operationMethod = operationMethod;
+    ret->opString = ast.opString;
     ret->left = std::move(leftEval);
     ret->left = std::move(leftEval);
     ret->right = std::move(rightEval);
     ret->right = std::move(rightEval);
     return ret;
     return ret;
@@ -282,3 +337,12 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::NewArrayExpres
     return ret;
     return ret;
 }
 }
 
 
+
+std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::CastExpression& ast, sem::Scope& scope)
+{
+    auto expr = unique_dynamic_cast<sem::Expression>(ast.expression->accept(*this, scope));
+    auto type = scope.getType(*ast.targetType);
+    return std::make_unique<sem::CastExpression>(
+        std::move(expr), std::move(type), &ast);
+}
+

+ 3 - 1
src/AstVisitor.h

@@ -49,7 +49,8 @@ class qlow::StructureVisitor :
         ast::IntConst,
         ast::IntConst,
         ast::UnaryOperation,
         ast::UnaryOperation,
         ast::BinaryOperation,
         ast::BinaryOperation,
-        ast::NewArrayExpression
+        ast::NewArrayExpression,
+        ast::CastExpression
     >
     >
 {
 {
 public:
 public:
@@ -73,6 +74,7 @@ public:
     ReturnType visit(ast::UnaryOperation& ast, sem::Scope& scope) override;
     ReturnType visit(ast::UnaryOperation& ast, sem::Scope& scope) override;
     ReturnType visit(ast::BinaryOperation& ast, sem::Scope& scope) override;
     ReturnType visit(ast::BinaryOperation& ast, sem::Scope& scope) override;
     ReturnType visit(ast::NewArrayExpression& ast, sem::Scope& scope) override;
     ReturnType visit(ast::NewArrayExpression& ast, sem::Scope& scope) override;
+    ReturnType visit(ast::CastExpression& ast, sem::Scope& scope) override;
 };
 };
 
 
 
 

+ 54 - 1
src/Builtin.cpp

@@ -47,12 +47,65 @@ sem::NativeScope qlow::sem::generateNativeScope(void)
         
         
         native->nativeMethods.insert(
         native->nativeMethods.insert(
             { "+",
             { "+",
-                std::make_unique<BinaryNativeMethod>( native, native,
+                std::make_unique<BinaryNativeMethod>(native, native,
                 [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
                 [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
                     return builder.CreateAdd(a, b);
                     return builder.CreateAdd(a, b);
                 })
                 })
             }
             }
         );
         );
+        native->nativeMethods.insert(
+            { "-",
+                std::make_unique<BinaryNativeMethod>(native, native,
+                [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
+                    return builder.CreateSub(a, b);
+                })
+            }
+        );
+        native->nativeMethods.insert(
+            { "*",
+                std::make_unique<BinaryNativeMethod>(native, native,
+                [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
+                    return builder.CreateMul(a, b);
+                })
+            }
+        );
+        if (name[0] == 'U') {
+            native->nativeMethods.insert(
+                { "/",
+                    std::make_unique<BinaryNativeMethod>(native, native,
+                    [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
+                        return builder.CreateUDiv(a, b);
+                    })
+                }
+            );
+        }
+        else {
+            native->nativeMethods.insert(
+                { "/",
+                    std::make_unique<BinaryNativeMethod>(native, native,
+                    [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
+                        return builder.CreateSDiv(a, b);
+                    })
+                }
+            );
+        }
+        
+        native->nativeMethods.insert(
+            { "==",
+                std::make_unique<BinaryNativeMethod>(std::make_shared<NativeType>(NativeType::BOOLEAN), native,
+                [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
+                    return builder.CreateICmpEQ(a, b);
+                })
+            }
+        );
+        native->nativeMethods.insert(
+            { "!=",
+                std::make_unique<BinaryNativeMethod>(std::make_shared<NativeType>(NativeType::BOOLEAN), native,
+                [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* b) {
+                    return builder.CreateICmpNE(a, b);
+                })
+            }
+        );
         
         
         scope.types.insert({ name, std::make_unique
         scope.types.insert({ name, std::make_unique
             <std::shared_ptr<NativeType>>(std::move(native)) });
             <std::shared_ptr<NativeType>>(std::move(native)) });

+ 2 - 1
src/CodeGeneration.cpp

@@ -202,10 +202,11 @@ void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Modul
 
 
     if (!target) {
     if (!target) {
         logger.debug() << "could not create target: " << error << std::endl;
         logger.debug() << "could not create target: " << error << std::endl;
+        throw "internal error";
     }
     }
 
 
     TargetOptions targetOptions;
     TargetOptions targetOptions;
-    auto relocModel = llvm::Optional<llvm::Reloc::Model>();
+    auto relocModel = llvm::Optional<llvm::Reloc::Model>(llvm::Reloc::Model::PIC_);
     std::unique_ptr<TargetMachine> targetMachine(target->createTargetMachine(targetTriple, cpu,
     std::unique_ptr<TargetMachine> targetMachine(target->createTargetMachine(targetTriple, cpu,
             features, targetOptions, relocModel));
             features, targetOptions, relocModel));
 
 

+ 41 - 57
src/CodegenVisitor.cpp

@@ -25,6 +25,27 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::LocalVariableExpression& lve,
 }
 }
 
 
 
 
+llvm::Value* ExpressionCodegenVisitor::visit(sem::UnaryOperation& unop, llvm::IRBuilder<>& builder)
+{
+    using llvm::Value;
+    auto value = unop.arg->accept(*this, builder);
+    auto& type = unop.arg->type;
+    
+    if (type->equals(sem::NativeType(sem::NativeType::Type::VOID)))
+        throw "invalid type to negate";
+
+    /*
+    switch (unop.op) {
+        case ast::Operation::Operator::MINUS:
+            return builder.CreateNeg(value, "negate");
+        case ast::Operation::Operator::NOT:
+            return builder.CreateNot(value, "not");
+        default:
+            throw "operator not supported";
+    }*/
+}
+
+
 llvm::Value* ExpressionCodegenVisitor::visit(sem::BinaryOperation& binop, llvm::IRBuilder<>& builder)
 llvm::Value* ExpressionCodegenVisitor::visit(sem::BinaryOperation& binop, llvm::IRBuilder<>& builder)
 {
 {
     using llvm::Value;
     using llvm::Value;
@@ -35,37 +56,7 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::BinaryOperation& binop, llvm::
     auto& leftType = binop.left->type;
     auto& leftType = binop.left->type;
     auto& rightType = binop.right->type;
     auto& rightType = binop.right->type;
     
     
-    if (!leftType->isNativeType() || !rightType->isNativeType())
-        throw "invalid types in BinaryOperation";
-    
-    std::string methodName;
-    
-    switch (binop.op) {
-        case ast::Operation::Operator::PLUS:
-            methodName = "+";
-        case ast::Operation::Operator::MINUS:
-            methodName = "-";
-        case ast::Operation::Operator::ASTERISK:
-            methodName = "*";
-        case ast::Operation::Operator::SLASH:
-            methodName = "/";
-            
-        case ast::Operation::Operator::AND:
-            methodName = "and";
-        case ast::Operation::Operator::OR:
-            methodName = "or";
-        case ast::Operation::Operator::XOR:
-            methodName = "xor";
-            
-        case ast::Operation::Operator::EQUALS:
-            methodName = "==";
-        case ast::Operation::Operator::NOT_EQUALS:
-            methodName = "!=";
-            ;
-    }
-    
-    sem::Method* operation =
-        leftType->getScope().resolveMethod(methodName, {leftType, rightType});
+    sem::Method* operation = binop.operationMethod;
     
     
     if (operation != nullptr) {
     if (operation != nullptr) {
         if (sem::NativeMethod* nm = dynamic_cast<sem::NativeMethod*>(operation); nm) {
         if (sem::NativeMethod* nm = dynamic_cast<sem::NativeMethod*>(operation); nm) {
@@ -75,19 +66,13 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::BinaryOperation& binop, llvm::
             throw "only native operations supported at the moment";
             throw "only native operations supported at the moment";
     }
     }
     else {
     else {
-        auto errMsg = std::string("operator ") + methodName + " not found for types "
-            + leftType->asString() + " and " + rightType->asString();
-        throw SemanticError(SemanticError::OPERATOR_NOT_FOUND, errMsg,
-            binop.astNode->pos
-        );
+        throw "internal error: operation method null";
     }
     }
-    
         
         
     if (left == nullptr) {
     if (left == nullptr) {
         printf("WOW: %s\n", binop.left->toString().c_str());
         printf("WOW: %s\n", binop.left->toString().c_str());
     }
     }
     
     
-    
     Value* implicitelyCastedRight = right;
     Value* implicitelyCastedRight = right;
     if (!leftType->equals(*rightType))
     if (!leftType->equals(*rightType))
         implicitelyCastedRight = dynamic_cast<sem::NativeType*>(leftType.get())->generateImplicitCast(right);
         implicitelyCastedRight = dynamic_cast<sem::NativeType*>(leftType.get())->generateImplicitCast(right);
@@ -96,7 +81,7 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::BinaryOperation& binop, llvm::
         // TODO allow integer operations
         // TODO allow integer operations
     }
     }
     
     
-    
+   /* 
     // TODO insert type checks
     // TODO insert type checks
     switch (binop.op) {
     switch (binop.op) {
         case ast::Operation::Operator::PLUS:
         case ast::Operation::Operator::PLUS:
@@ -119,27 +104,17 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::BinaryOperation& binop, llvm::
             return builder.CreateICmpEQ(left, right, "equals");
             return builder.CreateICmpEQ(left, right, "equals");
         case ast::Operation::Operator::NOT_EQUALS:
         case ast::Operation::Operator::NOT_EQUALS:
             return builder.CreateICmpNE(left, right, "not_equals");
             return builder.CreateICmpNE(left, right, "not_equals");
-    }
+    }*/
 }
 }
 
 
 
 
-llvm::Value* ExpressionCodegenVisitor::visit(sem::UnaryOperation& unop, llvm::IRBuilder<>& builder)
+llvm::Value* ExpressionCodegenVisitor::visit(sem::CastExpression& cast, llvm::IRBuilder<>& builder)
 {
 {
-    using llvm::Value;
-    auto value = unop.arg->accept(*this, builder);
-    auto& type = unop.arg->type;
-    
-    if (type->equals(sem::NativeType(sem::NativeType::Type::VOID)))
-        throw "invalid type to negate";
-
-    switch (unop.op) {
-        case ast::Operation::Operator::MINUS:
-            return builder.CreateNeg(value, "negate");
-        case ast::Operation::Operator::NOT:
-            return builder.CreateNot(value, "not");
-        default:
-            throw "operator not supported";
-    }
+    return builder.CreateCast(
+        llvm::Instruction::CastOps::SExt,
+        cast.expression->accept(*this, builder),
+        cast.targetType->getLlvmType(builder.getContext())
+    );
 }
 }
 
 
 
 
@@ -306,9 +281,18 @@ llvm::Value* StatementVisitor::visit(sem::FeatureCallStatement& fc, gen::Functio
     llvm::IRBuilder<> builder(fg.getContext());
     llvm::IRBuilder<> builder(fg.getContext());
     builder.SetInsertPoint(fg.getCurrentBlock());
     builder.SetInsertPoint(fg.getCurrentBlock());
     //llvm::Constant* c = module->getOrInsertFunction(fc.expr->callee->name, {});
     //llvm::Constant* c = module->getOrInsertFunction(fc.expr->callee->name, {});
+    
+    return fc.expr->accept(fg.expressionVisitor, builder);
+    
+    /*
     llvm::Function* f = fc.expr->callee->llvmNode;
     llvm::Function* f = fc.expr->callee->llvmNode;
+    std::vector<llvm::Value*> arguments;
+    for (auto& arg : fc.expr->arguments) {
+        arguments
+    }
     builder.CreateCall(f, {});
     builder.CreateCall(f, {});
-    return llvm::ConstantFP::get(fg.getContext(), llvm::APFloat(5.0));
+    */
+    // return llvm::ConstantFP::get(fg.getContext(), llvm::APFloat(5.0));
 }
 }
 
 
 
 

+ 4 - 2
src/CodegenVisitor.h

@@ -36,8 +36,9 @@ class qlow::ExpressionCodegenVisitor :
         llvm::IRBuilder<>,
         llvm::IRBuilder<>,
 
 
         sem::LocalVariableExpression,
         sem::LocalVariableExpression,
-        sem::BinaryOperation,
         sem::UnaryOperation,
         sem::UnaryOperation,
+        sem::BinaryOperation,
+        sem::CastExpression,
         sem::NewArrayExpression,
         sem::NewArrayExpression,
         sem::FeatureCallExpression,
         sem::FeatureCallExpression,
         sem::IntConst
         sem::IntConst
@@ -45,8 +46,9 @@ class qlow::ExpressionCodegenVisitor :
 {
 {
 public:
 public:
     llvm::Value* visit(sem::LocalVariableExpression& node, llvm::IRBuilder<>&) override;
     llvm::Value* visit(sem::LocalVariableExpression& node, llvm::IRBuilder<>&) override;
-    llvm::Value* visit(sem::BinaryOperation& node, llvm::IRBuilder<>&) override;
     llvm::Value* visit(sem::UnaryOperation& node, llvm::IRBuilder<>&) override;
     llvm::Value* visit(sem::UnaryOperation& node, llvm::IRBuilder<>&) override;
+    llvm::Value* visit(sem::BinaryOperation& node, llvm::IRBuilder<>&) override;
+    llvm::Value* visit(sem::CastExpression& node, llvm::IRBuilder<>&) override;
     llvm::Value* visit(sem::NewArrayExpression& node, llvm::IRBuilder<>&) override;
     llvm::Value* visit(sem::NewArrayExpression& node, llvm::IRBuilder<>&) override;
     llvm::Value* visit(sem::FeatureCallExpression& node, llvm::IRBuilder<>&) override;
     llvm::Value* visit(sem::FeatureCallExpression& node, llvm::IRBuilder<>&) override;
     llvm::Value* visit(sem::IntConst& node, llvm::IRBuilder<>&) override;
     llvm::Value* visit(sem::IntConst& node, llvm::IRBuilder<>&) override;

+ 1 - 0
src/ErrorReporting.cpp

@@ -128,6 +128,7 @@ void SemanticError::print(Logger& logger) const
         {DUPLICATE_FIELD_DECLARATION, "duplicate field declaration"},
         {DUPLICATE_FIELD_DECLARATION, "duplicate field declaration"},
         {DUPLICATE_METHOD_DEFINITION, "duplicate method definition"},
         {DUPLICATE_METHOD_DEFINITION, "duplicate method definition"},
         {OPERATOR_NOT_FOUND, ""},
         {OPERATOR_NOT_FOUND, ""},
+        {WRONG_NUMBER_OF_ARGUMENTS, "wrong number of arguments passed"},
     };
     };
     std::string& errMsg = error[errorCode];
     std::string& errMsg = error[errorCode];
     logger.logError(errMsg + (errMsg != "" ?  ": " : "") + message, where);
     logger.logError(errMsg + (errMsg != "" ?  ": " : "") + message, where);

+ 2 - 0
src/ErrorReporting.h

@@ -81,6 +81,8 @@ public:
         
         
         OPERATOR_NOT_FOUND,
         OPERATOR_NOT_FOUND,
         FEATURE_NOT_FOUND,
         FEATURE_NOT_FOUND,
+        WRONG_NUMBER_OF_ARGUMENTS,
+        TYPE_MISMATCH,
     };
     };
     
     
     
     

+ 8 - 0
src/Semantic.cpp

@@ -171,6 +171,7 @@ ReturnType ClassName::accept(Visitor& v, Arg arg) \
 
 
 ACCEPT_DEFINITION(LocalVariableExpression, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
 ACCEPT_DEFINITION(LocalVariableExpression, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
 ACCEPT_DEFINITION(BinaryOperation, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
 ACCEPT_DEFINITION(BinaryOperation, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
+ACCEPT_DEFINITION(CastExpression, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
 ACCEPT_DEFINITION(NewArrayExpression, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
 ACCEPT_DEFINITION(NewArrayExpression, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
 ACCEPT_DEFINITION(UnaryOperation, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
 ACCEPT_DEFINITION(UnaryOperation, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
 ACCEPT_DEFINITION(FeatureCallExpression, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
 ACCEPT_DEFINITION(FeatureCallExpression, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
@@ -215,6 +216,13 @@ std::string BinaryOperation::toString(void) const
 }
 }
 
 
 
 
+std::string CastExpression::toString(void) const
+{
+    return "CastExpression[" + expression->toString() + " to " +
+        targetType->toString() + "]";
+}
+
+
 std::string NewArrayExpression::toString(void) const
 std::string NewArrayExpression::toString(void) const
 {
 {
     return "NewArrayExpression[" + arrayType->toString() + "; " +
     return "NewArrayExpression[" + arrayType->toString() + "; " +

+ 30 - 3
src/Semantic.h

@@ -44,6 +44,8 @@ namespace qlow
         struct UnaryOperation;
         struct UnaryOperation;
         struct BinaryOperation;
         struct BinaryOperation;
         
         
+        struct CastExpression;
+        
         struct NewArrayExpression;
         struct NewArrayExpression;
 
 
         struct FeatureCallExpression;
         struct FeatureCallExpression;
@@ -234,7 +236,7 @@ struct qlow::sem::Expression :
 
 
 struct qlow::sem::Operation : public Expression
 struct qlow::sem::Operation : public Expression
 {
 {
-    ast::Operation::Operator op;
+    std::string opString;
     
     
     inline Operation(std::shared_ptr<Type> type) :
     inline Operation(std::shared_ptr<Type> type) :
         Expression{ std::move(type) }
         Expression{ std::move(type) }
@@ -279,6 +281,29 @@ struct qlow::sem::BinaryOperation : public Operation
 };
 };
 
 
 
 
+struct qlow::sem::CastExpression : public Expression
+{
+    std::unique_ptr<Expression> expression;
+    std::shared_ptr<Type> targetType;
+    
+    ast::CastExpression* astNode;
+    
+    inline CastExpression(std::unique_ptr<Expression> expression,
+                          std::shared_ptr<Type> type,
+                          ast::CastExpression* astNode) :
+        Expression{ type },
+        expression{ std::move(expression) },
+        targetType{ std::move(type) },
+        astNode{ astNode }
+    {
+    }
+    
+    virtual llvm::Value* accept(ExpressionCodegenVisitor& visitor, llvm::IRBuilder<>& arg2) override;
+    
+    virtual std::string toString(void) const override;
+};
+
+
 struct qlow::sem::NewArrayExpression : public Expression
 struct qlow::sem::NewArrayExpression : public Expression
 {
 {
     std::shared_ptr<Type> arrayType;
     std::shared_ptr<Type> arrayType;
@@ -313,10 +338,12 @@ struct qlow::sem::UnaryOperation : public Operation
 struct qlow::sem::FeatureCallExpression : public Expression
 struct qlow::sem::FeatureCallExpression : public Expression
 {
 {
     Method* callee;
     Method* callee;
+    std::unique_ptr<Expression> target;
     OwningList<Expression> arguments;
     OwningList<Expression> arguments;
     
     
-    inline FeatureCallExpression(std::shared_ptr<Type> type) :
-        Expression{ std::move(type) }
+    inline FeatureCallExpression(std::unique_ptr<Expression> target,
+                                 Method* callee) :
+        Expression{ callee->returnType }
     {
     {
     }
     }
     
     

+ 5 - 0
src/Type.cpp

@@ -204,6 +204,11 @@ llvm::Type* sem::NativeType::getLlvmType (llvm::LLVMContext& context) const
 bool sem::NativeType::equals(const sem::Type& other) const
 bool sem::NativeType::equals(const sem::Type& other) const
 {
 {
     if (auto* oct = dynamic_cast<const NativeType*>(&other); oct) {
     if (auto* oct = dynamic_cast<const NativeType*>(&other); oct) {
+        if (this->type == Type::INTEGER || this->type == Type::INT32) {
+            if (oct->type == Type::INTEGER || oct->type == Type::INT32)
+                // Int32 == Integer
+                return true;
+        }
         return this->type == oct->type;
         return this->type == oct->type;
     }
     }
     else {
     else {

+ 2 - 0
src/lexer.l

@@ -113,11 +113,13 @@ UTF8CHAR [\x00-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xe
 "or"                    SET_STRING; return OR;
 "or"                    SET_STRING; return OR;
 "xor"                   SET_STRING; return XOR;
 "xor"                   SET_STRING; return XOR;
 "not"                   SET_STRING; return NOT;
 "not"                   SET_STRING; return NOT;
+"as"                    return SET_TOKEN(AS);
 
 
 "+"                     SET_STRING; return PLUS;
 "+"                     SET_STRING; return PLUS;
 "-"                     SET_STRING; return MINUS;
 "-"                     SET_STRING; return MINUS;
 "*"                     SET_STRING; return ASTERISK;
 "*"                     SET_STRING; return ASTERISK;
 "/"                     SET_STRING; return SLASH;
 "/"                     SET_STRING; return SLASH;
+[\+\-\*\/=!<>]+         SET_STRING; return CUSTOM_OPERATOR;
 
 
 "("                     return SET_TOKEN(ROUND_LEFT);
 "("                     return SET_TOKEN(ROUND_LEFT);
 ")"                     return SET_TOKEN(ROUND_RIGHT);
 ")"                     return SET_TOKEN(ROUND_RIGHT);

+ 34 - 17
src/parser.y

@@ -104,7 +104,6 @@ typedef qlow::CodePosition QLOW_PARSER_LTYPE;
     qlow::ast::WhileBlock* whileBlock;    
     qlow::ast::WhileBlock* whileBlock;    
     qlow::ast::Statement* statement;
     qlow::ast::Statement* statement;
     qlow::ast::Expression* expression;
     qlow::ast::Expression* expression;
-    qlow::ast::Operation::Operator op;
 
 
     qlow::ast::FieldDeclaration* fieldDeclaration;
     qlow::ast::FieldDeclaration* fieldDeclaration;
     qlow::ast::MethodDefinition* methodDefinition;
     qlow::ast::MethodDefinition* methodDefinition;
@@ -118,6 +117,7 @@ typedef qlow::CodePosition QLOW_PARSER_LTYPE;
     qlow::ast::BinaryOperation* binaryOperation;
     qlow::ast::BinaryOperation* binaryOperation;
 
 
     qlow::ast::NewArrayExpression* newArrayExpression;
     qlow::ast::NewArrayExpression* newArrayExpression;
+    qlow::ast::CastExpression* castExpression;
 
 
     const char* cString;
     const char* cString;
     std::string* string;
     std::string* string;
@@ -129,7 +129,7 @@ typedef qlow::CodePosition QLOW_PARSER_LTYPE;
 %token <string> INT_LITERAL
 %token <string> INT_LITERAL
 %token <string> ASTERISK SLASH PLUS MINUS EQUALS NOT_EQUALS AND OR XOR CUSTOM_OPERATOR
 %token <string> ASTERISK SLASH PLUS MINUS EQUALS NOT_EQUALS AND OR XOR CUSTOM_OPERATOR
 %token <token> TRUE FALSE
 %token <token> TRUE FALSE
-%token <token> CLASS DO END IF ELSE WHILE RETURN NEW EXTERN
+%token <token> CLASS DO END IF ELSE WHILE RETURN NEW EXTERN AS
 %token <token> NEW_LINE
 %token <token> NEW_LINE
 %token <token> SEMICOLON COLON COMMA DOT ASSIGN
 %token <token> SEMICOLON COLON COMMA DOT ASSIGN
 %token <token> ROUND_LEFT ROUND_RIGHT SQUARE_LEFT SQUARE_RIGHT
 %token <token> ROUND_LEFT ROUND_RIGHT SQUARE_LEFT SQUARE_RIGHT
@@ -152,21 +152,23 @@ typedef qlow::CodePosition QLOW_PARSER_LTYPE;
 %type <whileBlock> whileBlock
 %type <whileBlock> whileBlock
 %type <statement> statement
 %type <statement> statement
 %type <expression> expression operationExpression paranthesesExpression
 %type <expression> expression operationExpression paranthesesExpression
-%type <op> operator
 %type <featureCall> featureCall
 %type <featureCall> featureCall
 %type <assignmentStatement> assignmentStatement 
 %type <assignmentStatement> assignmentStatement 
 %type <returnStatement> returnStatement 
 %type <returnStatement> returnStatement 
 %type <localVariableStatement> localVariableStatement
 %type <localVariableStatement> localVariableStatement
+%type <string> operator
 %type <unaryOperation> unaryOperation
 %type <unaryOperation> unaryOperation
 %type <binaryOperation> binaryOperation
 %type <binaryOperation> binaryOperation
 %type <newArrayExpression> newArrayExpression
 %type <newArrayExpression> newArrayExpression
+%type <castExpression> castExpression
 
 
 %destructor { } <token>
 %destructor { } <token>
-%destructor { } <op>
+//%destructor { if ($$) delete $$ } <op>
 %destructor { } <topLevel> // don't delete everything ;)
 %destructor { } <topLevel> // don't delete everything ;)
 %destructor { if ($$) delete $$; } <*>
 %destructor { if ($$) delete $$; } <*>
 
 
 %left DOT
 %left DOT
+%nonassoc AS 
 %left ASTERISK SLASH
 %left ASTERISK SLASH
 %left PLUS MINUS
 %left PLUS MINUS
 %left EQUALS
 %left EQUALS
@@ -498,6 +500,10 @@ expression:
         $$ = $1;
         $$ = $1;
     }
     }
     |
     |
+    castExpression {
+        $$ = $1;
+    }
+    |
     INT_LITERAL {
     INT_LITERAL {
         $$ = new IntConst(std::move(*$1), @$);
         $$ = new IntConst(std::move(*$1), @$);
         delete $1;
         delete $1;
@@ -524,40 +530,45 @@ operationExpression:
 binaryOperation:
 binaryOperation:
     expression operator expression {
     expression operator expression {
         $$ = new BinaryOperation(std::unique_ptr<Expression>($1), 
         $$ = new BinaryOperation(std::unique_ptr<Expression>($1), 
-            std::unique_ptr<Expression>($3), $2, @$);
+            std::unique_ptr<Expression>($3), *$2, @$, @2);
+        delete $2; $2 = nullptr;
     };
     };
 
 
 
 
 unaryOperation:
 unaryOperation:
     expression operator {
     expression operator {
         $$ = new UnaryOperation(std::unique_ptr<Expression>($1),
         $$ = new UnaryOperation(std::unique_ptr<Expression>($1),
-            UnaryOperation::SUFFIX, $2, @$);
+            UnaryOperation::SUFFIX, *$2, @$, @2);
+        delete $2; $2 = nullptr;
     }
     }
     |
     |
     operator expression {
     operator expression {
         $$ = new UnaryOperation(std::unique_ptr<Expression>($2),
         $$ = new UnaryOperation(std::unique_ptr<Expression>($2),
-            UnaryOperation::PREFIX, $1, @$);
+            UnaryOperation::PREFIX, *$1, @$, @2);
+        delete $1; $1 = nullptr;
     };
     };
 
 
 
 
 operator:
 operator:
-    PLUS { $$ = qlow::ast::Operation::Operator::PLUS; }
+    PLUS { $$ = $1; }
+    |
+    MINUS { $$ = $1; }
     |
     |
-    MINUS { $$ = qlow::ast::Operation::Operator::MINUS; }
+    ASTERISK { $$ = $1; }
     |
     |
-    ASTERISK { $$ = qlow::ast::Operation::Operator::ASTERISK; }
+    SLASH { $$ = $1; }
     |
     |
-    SLASH { $$ = qlow::ast::Operation::Operator::SLASH; }
+    EQUALS { $$ = $1; }
     |
     |
-    EQUALS { $$ = qlow::ast::Operation::Operator::EQUALS; }
+    NOT_EQUALS { $$ = $1; }
     |
     |
-    NOT_EQUALS { $$ = qlow::ast::Operation::Operator::NOT_EQUALS; }
+    AND { $$ = $1; }
     |
     |
-    AND { $$ = qlow::ast::Operation::Operator::AND; }
+    OR { $$ = $1; }
     |
     |
-    OR { $$ = qlow::ast::Operation::Operator::OR; }
+    XOR { $$ = $1; }
     |
     |
-    XOR { $$ = qlow::ast::Operation::Operator::XOR; };
+    CUSTOM_OPERATOR { $$ = $1; };
 
 
 
 
 paranthesesExpression:
 paranthesesExpression:
@@ -567,7 +578,13 @@ paranthesesExpression:
 
 
 newArrayExpression:
 newArrayExpression:
     NEW SQUARE_LEFT type SEMICOLON expression SQUARE_RIGHT {
     NEW SQUARE_LEFT type SEMICOLON expression SQUARE_RIGHT {
-        
+        $$ = nullptr;
+    };
+    
+castExpression:
+    expression AS type {
+        $$ = new CastExpression(std::unique_ptr<Expression>($1),
+            std::unique_ptr<qlow::ast::Type>($3), @$);
     };
     };
 
 
 assignmentStatement:
 assignmentStatement:

+ 2 - 1
src/test.qlw

@@ -6,6 +6,7 @@ fast_fibonacci(i: Integer): Integer do
     count := i
     count := i
     a := 0
     a := 0
     b := 1
     b := 1
+    //b := a <=> b
     while count != 0 do
     while count != 0 do
         temp := a
         temp := a
         a := a + b
         a := a + b
@@ -26,7 +27,7 @@ bignumbers do
     //b := a + c
     //b := a + c
 end
 end
 
 
-main do
+main2 do
     value: Integer
     value: Integer
     do_shit
     do_shit
 end
 end

+ 10 - 2
src/tests/structs.qlw

@@ -3,14 +3,22 @@
 class Vec
 class Vec
     x: Integer
     x: Integer
     y: Integer
     y: Integer
+
+    yuhu: Integer do
+        return 5
+    end
 end
 end
 
 
 
 
-main do
+main: Integer do
     var: Vec
     var: Vec
     value: Integer
     value: Integer
+    value := 5
 
 
-    var.x := 4
+//    value := var.yuhu
+//    var.x := 4
+//    var.hohoo := 4
+    return value
 end
 end
 
 
 
 

+ 1 - 1
vim/syntax/qlow.vim

@@ -10,7 +10,7 @@ endif
 
 
 
 
 
 
-syn keyword keywordy class do end if while return extern
+syn keyword keywordy class do end if while return extern as
 syn keyword typey Integer Boolean
 syn keyword typey Integer Boolean
 syn keyword typey String Char 
 syn keyword typey String Char 
 syn keyword typey Int8 Int16 Int32 Int64 Int128 UInt8 UInt16 UInt32 UInt64 UInt128
 syn keyword typey Int8 Int16 Int32 Int64 Int128 UInt8 UInt16 UInt32 UInt64 UInt128