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(BinaryOperation, StructureVisitor)
 ACCEPT_DEFINITION(NewArrayExpression, StructureVisitor)
-
+ACCEPT_DEFINITION(CastExpression, StructureVisitor)
 
 
 Statement::~Statement(void)

+ 39 - 7
src/Ast.h

@@ -75,6 +75,8 @@ namespace qlow
         struct BinaryOperation;
         
         struct NewArrayExpression;
+        
+        struct CastExpression;
     }
 
     namespace sem
@@ -431,11 +433,14 @@ struct qlow::ast::IntConst : public Expression
 struct qlow::ast::Operation : public Expression
 {
     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 },
         Expression{ cp },
-        opString{ opString }
+        opString{ opString },
+        opPos{ opPos }
     {
     }
 };
@@ -453,9 +458,11 @@ struct qlow::ast::UnaryOperation : public Operation
     std::unique_ptr<Expression> expr;
 
     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 },
-        Operation{ op, cp },
+        Operation{ op, cp, opPos },
         side{ side },
         expr{ std::move(expr) }
     {
@@ -470,10 +477,16 @@ struct qlow::ast::BinaryOperation : public Operation
     std::unique_ptr<Expression> left;
     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 },
-        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
 
 

+ 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> target = nullptr;
+    std::unique_ptr<sem::Expression> target = nullptr;
     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);
     }
     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) {
             auto argument = arg->accept(*this, scope);
             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 ret = std::make_unique<sem::UnaryOperation>(argument->type);
             // TODO not a feasible assumption
-    ret->op = ast.op;
+    ret->opString = ast.opString;
     ret->side = ast.side;
     ret->arg = std::move(argument);
     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));
     
     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);
     
-    ret->op = ast.op;
+    ret->operationMethod = operationMethod;
+    ret->opString = ast.opString;
     ret->left = std::move(leftEval);
     ret->right = std::move(rightEval);
     return ret;
@@ -282,3 +337,12 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::NewArrayExpres
     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::UnaryOperation,
         ast::BinaryOperation,
-        ast::NewArrayExpression
+        ast::NewArrayExpression,
+        ast::CastExpression
     >
 {
 public:
@@ -73,6 +74,7 @@ public:
     ReturnType visit(ast::UnaryOperation& 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::CastExpression& ast, sem::Scope& scope) override;
 };
 
 

+ 54 - 1
src/Builtin.cpp

@@ -47,12 +47,65 @@ sem::NativeScope qlow::sem::generateNativeScope(void)
         
         native->nativeMethods.insert(
             { "+",
-                std::make_unique<BinaryNativeMethod>( native, native,
+                std::make_unique<BinaryNativeMethod>(native, native,
                 [] (llvm::IRBuilder<>& builder, llvm::Value* a, llvm::Value* 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
             <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) {
         logger.debug() << "could not create target: " << error << std::endl;
+        throw "internal error";
     }
 
     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,
             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)
 {
     using llvm::Value;
@@ -35,37 +56,7 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::BinaryOperation& binop, llvm::
     auto& leftType = binop.left->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 (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";
     }
     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) {
         printf("WOW: %s\n", binop.left->toString().c_str());
     }
     
-    
     Value* implicitelyCastedRight = right;
     if (!leftType->equals(*rightType))
         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 insert type checks
     switch (binop.op) {
         case ast::Operation::Operator::PLUS:
@@ -119,27 +104,17 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::BinaryOperation& binop, llvm::
             return builder.CreateICmpEQ(left, right, "equals");
         case ast::Operation::Operator::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());
     builder.SetInsertPoint(fg.getCurrentBlock());
     //llvm::Constant* c = module->getOrInsertFunction(fc.expr->callee->name, {});
+    
+    return fc.expr->accept(fg.expressionVisitor, builder);
+    
+    /*
     llvm::Function* f = fc.expr->callee->llvmNode;
+    std::vector<llvm::Value*> arguments;
+    for (auto& arg : fc.expr->arguments) {
+        arguments
+    }
     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<>,
 
         sem::LocalVariableExpression,
-        sem::BinaryOperation,
         sem::UnaryOperation,
+        sem::BinaryOperation,
+        sem::CastExpression,
         sem::NewArrayExpression,
         sem::FeatureCallExpression,
         sem::IntConst
@@ -45,8 +46,9 @@ class qlow::ExpressionCodegenVisitor :
 {
 public:
     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::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::FeatureCallExpression& 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_METHOD_DEFINITION, "duplicate method definition"},
         {OPERATOR_NOT_FOUND, ""},
+        {WRONG_NUMBER_OF_ARGUMENTS, "wrong number of arguments passed"},
     };
     std::string& errMsg = error[errorCode];
     logger.logError(errMsg + (errMsg != "" ?  ": " : "") + message, where);

+ 2 - 0
src/ErrorReporting.h

@@ -81,6 +81,8 @@ public:
         
         OPERATOR_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(BinaryOperation, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
+ACCEPT_DEFINITION(CastExpression, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
 ACCEPT_DEFINITION(NewArrayExpression, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
 ACCEPT_DEFINITION(UnaryOperation, 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
 {
     return "NewArrayExpression[" + arrayType->toString() + "; " +

+ 30 - 3
src/Semantic.h

@@ -44,6 +44,8 @@ namespace qlow
         struct UnaryOperation;
         struct BinaryOperation;
         
+        struct CastExpression;
+        
         struct NewArrayExpression;
 
         struct FeatureCallExpression;
@@ -234,7 +236,7 @@ struct qlow::sem::Expression :
 
 struct qlow::sem::Operation : public Expression
 {
-    ast::Operation::Operator op;
+    std::string opString;
     
     inline Operation(std::shared_ptr<Type> 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
 {
     std::shared_ptr<Type> arrayType;
@@ -313,10 +338,12 @@ struct qlow::sem::UnaryOperation : public Operation
 struct qlow::sem::FeatureCallExpression : public Expression
 {
     Method* callee;
+    std::unique_ptr<Expression> target;
     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
 {
     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;
     }
     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;
 "xor"                   SET_STRING; return XOR;
 "not"                   SET_STRING; return NOT;
+"as"                    return SET_TOKEN(AS);
 
 "+"                     SET_STRING; return PLUS;
 "-"                     SET_STRING; return MINUS;
 "*"                     SET_STRING; return ASTERISK;
 "/"                     SET_STRING; return SLASH;
+[\+\-\*\/=!<>]+         SET_STRING; return CUSTOM_OPERATOR;
 
 "("                     return SET_TOKEN(ROUND_LEFT);
 ")"                     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::Statement* statement;
     qlow::ast::Expression* expression;
-    qlow::ast::Operation::Operator op;
 
     qlow::ast::FieldDeclaration* fieldDeclaration;
     qlow::ast::MethodDefinition* methodDefinition;
@@ -118,6 +117,7 @@ typedef qlow::CodePosition QLOW_PARSER_LTYPE;
     qlow::ast::BinaryOperation* binaryOperation;
 
     qlow::ast::NewArrayExpression* newArrayExpression;
+    qlow::ast::CastExpression* castExpression;
 
     const char* cString;
     std::string* string;
@@ -129,7 +129,7 @@ typedef qlow::CodePosition QLOW_PARSER_LTYPE;
 %token <string> INT_LITERAL
 %token <string> ASTERISK SLASH PLUS MINUS EQUALS NOT_EQUALS AND OR XOR CUSTOM_OPERATOR
 %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> SEMICOLON COLON COMMA DOT ASSIGN
 %token <token> ROUND_LEFT ROUND_RIGHT SQUARE_LEFT SQUARE_RIGHT
@@ -152,21 +152,23 @@ typedef qlow::CodePosition QLOW_PARSER_LTYPE;
 %type <whileBlock> whileBlock
 %type <statement> statement
 %type <expression> expression operationExpression paranthesesExpression
-%type <op> operator
 %type <featureCall> featureCall
 %type <assignmentStatement> assignmentStatement 
 %type <returnStatement> returnStatement 
 %type <localVariableStatement> localVariableStatement
+%type <string> operator
 %type <unaryOperation> unaryOperation
 %type <binaryOperation> binaryOperation
 %type <newArrayExpression> newArrayExpression
+%type <castExpression> castExpression
 
 %destructor { } <token>
-%destructor { } <op>
+//%destructor { if ($$) delete $$ } <op>
 %destructor { } <topLevel> // don't delete everything ;)
 %destructor { if ($$) delete $$; } <*>
 
 %left DOT
+%nonassoc AS 
 %left ASTERISK SLASH
 %left PLUS MINUS
 %left EQUALS
@@ -498,6 +500,10 @@ expression:
         $$ = $1;
     }
     |
+    castExpression {
+        $$ = $1;
+    }
+    |
     INT_LITERAL {
         $$ = new IntConst(std::move(*$1), @$);
         delete $1;
@@ -524,40 +530,45 @@ operationExpression:
 binaryOperation:
     expression operator expression {
         $$ = 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:
     expression operator {
         $$ = new UnaryOperation(std::unique_ptr<Expression>($1),
-            UnaryOperation::SUFFIX, $2, @$);
+            UnaryOperation::SUFFIX, *$2, @$, @2);
+        delete $2; $2 = nullptr;
     }
     |
     operator expression {
         $$ = new UnaryOperation(std::unique_ptr<Expression>($2),
-            UnaryOperation::PREFIX, $1, @$);
+            UnaryOperation::PREFIX, *$1, @$, @2);
+        delete $1; $1 = nullptr;
     };
 
 
 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:
@@ -567,7 +578,13 @@ paranthesesExpression:
 
 newArrayExpression:
     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:

+ 2 - 1
src/test.qlw

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

+ 10 - 2
src/tests/structs.qlw

@@ -3,14 +3,22 @@
 class Vec
     x: Integer
     y: Integer
+
+    yuhu: Integer do
+        return 5
+    end
 end
 
 
-main do
+main: Integer do
     var: Vec
     value: Integer
+    value := 5
 
-    var.x := 4
+//    value := var.yuhu
+//    var.x := 4
+//    var.hohoo := 4
+    return value
 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 String Char 
 syn keyword typey Int8 Int16 Int32 Int64 Int128 UInt8 UInt16 UInt32 UInt64 UInt128