|  | @@ -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));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 |