|  | @@ -9,26 +9,28 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  using namespace qlow;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -std::pair<llvm::Value*, sem::Type*> ExpressionCodegenVisitor::visit(sem::LocalVariableExpression& lve, llvm::IRBuilder<>& builder)
 | 
	
		
			
				|  |  | +llvm::Value* ExpressionCodegenVisitor::visit(sem::LocalVariableExpression& lve, llvm::IRBuilder<>& builder)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      assert(lve.var->allocaInst != nullptr);
 | 
	
		
			
				|  |  |      if (llvm::dyn_cast<llvm::AllocaInst>(lve.var->allocaInst)) {
 | 
	
		
			
				|  |  |          llvm::Value* val = builder.CreateLoad(lve.var->allocaInst);
 | 
	
		
			
				|  |  | -        return { val, lve.var->type.get() };
 | 
	
		
			
				|  |  | +        return val;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      else {
 | 
	
		
			
				|  |  | -        return { lve.var->allocaInst, lve.var->type.get() };
 | 
	
		
			
				|  |  | +        return lve.var->allocaInst;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -std::pair<llvm::Value*, sem::Type*> ExpressionCodegenVisitor::visit(sem::BinaryOperation& binop, llvm::IRBuilder<>& builder)
 | 
	
		
			
				|  |  | +llvm::Value* ExpressionCodegenVisitor::visit(sem::BinaryOperation& binop, llvm::IRBuilder<>& builder)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      using llvm::Value;
 | 
	
		
			
				|  |  |      using sem::Type;
 | 
	
		
			
				|  |  | -    auto [left, leftType] = binop.left->accept(*this, builder);
 | 
	
		
			
				|  |  | -    auto [right, rightType] = binop.right->accept(*this, builder);
 | 
	
		
			
				|  |  | +    auto left = binop.left->accept(*this, builder);
 | 
	
		
			
				|  |  | +    auto right = binop.right->accept(*this, builder);
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  | +    auto& leftType = binop.left->type;
 | 
	
		
			
				|  |  | +    auto& rightType = binop.right->type;
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  |      if (!leftType->isNativeType() || !rightType->isNativeType())
 | 
	
		
			
				|  |  |          throw "invalid types in BinaryOperation";
 | 
	
	
		
			
				|  | @@ -41,9 +43,9 @@ std::pair<llvm::Value*, sem::Type*> ExpressionCodegenVisitor::visit(sem::BinaryO
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  |      Value* implicitelyCastedRight = right;
 | 
	
		
			
				|  |  |      if (!leftType->equals(*rightType))
 | 
	
		
			
				|  |  | -        implicitelyCastedRight = dynamic_cast<sem::NativeType*>(leftType)->generateImplicitCast(right);
 | 
	
		
			
				|  |  | +        implicitelyCastedRight = dynamic_cast<sem::NativeType*>(leftType.get())->generateImplicitCast(right);
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  | -    if (dynamic_cast<sem::NativeType*>(leftType)->isIntegerType()) {
 | 
	
		
			
				|  |  | +    if (dynamic_cast<sem::NativeType*>(leftType.get())->isIntegerType()) {
 | 
	
		
			
				|  |  |          // TODO allow integer operations
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      
 | 
	
	
		
			
				|  | @@ -51,55 +53,56 @@ std::pair<llvm::Value*, sem::Type*> ExpressionCodegenVisitor::visit(sem::BinaryO
 | 
	
		
			
				|  |  |      // TODO insert type checks
 | 
	
		
			
				|  |  |      switch (binop.op) {
 | 
	
		
			
				|  |  |          case ast::Operation::Operator::PLUS:
 | 
	
		
			
				|  |  | -            return { builder.CreateAdd(left, right, "add"), leftType };
 | 
	
		
			
				|  |  | +            return builder.CreateAdd(left, right, "add");
 | 
	
		
			
				|  |  |          case ast::Operation::Operator::MINUS:
 | 
	
		
			
				|  |  | -            return { builder.CreateSub(left, right, "sub"), leftType };
 | 
	
		
			
				|  |  | +            return builder.CreateSub(left, right, "sub");
 | 
	
		
			
				|  |  |          case ast::Operation::Operator::ASTERISK:
 | 
	
		
			
				|  |  | -            return { builder.CreateMul(left, right, "mul"), leftType };
 | 
	
		
			
				|  |  | +            return builder.CreateMul(left, right, "mul");
 | 
	
		
			
				|  |  |          case ast::Operation::Operator::SLASH:
 | 
	
		
			
				|  |  | -            return { builder.CreateSDiv(left, right, "sdiv"), leftType };
 | 
	
		
			
				|  |  | +            return builder.CreateSDiv(left, right, "sdiv");
 | 
	
		
			
				|  |  |              
 | 
	
		
			
				|  |  |          case ast::Operation::Operator::AND:
 | 
	
		
			
				|  |  | -            return { builder.CreateAnd(left, right, "and"), Type::BOOLEAN };
 | 
	
		
			
				|  |  | +            return builder.CreateAnd(left, right, "and");
 | 
	
		
			
				|  |  |          case ast::Operation::Operator::OR:
 | 
	
		
			
				|  |  | -            return { builder.CreateOr(left, right, "or"), Type::BOOLEAN };
 | 
	
		
			
				|  |  | +            return builder.CreateOr(left, right, "or");
 | 
	
		
			
				|  |  |          case ast::Operation::Operator::XOR:
 | 
	
		
			
				|  |  | -            return { builder.CreateXor(left, right, "xor"), Type::BOOLEAN };
 | 
	
		
			
				|  |  | +            return builder.CreateXor(left, right, "xor");
 | 
	
		
			
				|  |  |              
 | 
	
		
			
				|  |  |          case ast::Operation::Operator::EQUALS:
 | 
	
		
			
				|  |  | -            return { builder.CreateICmpEQ(left, right, "equals"), Type::BOOLEAN };
 | 
	
		
			
				|  |  | +            return builder.CreateICmpEQ(left, right, "equals");
 | 
	
		
			
				|  |  |          case ast::Operation::Operator::NOT_EQUALS:
 | 
	
		
			
				|  |  | -            return { builder.CreateICmpNE(left, right, "not_equals"), Type::BOOLEAN };
 | 
	
		
			
				|  |  | +            return builder.CreateICmpNE(left, right, "not_equals");
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -std::pair<llvm::Value*, sem::Type*> ExpressionCodegenVisitor::visit(sem::UnaryOperation& unop, llvm::IRBuilder<>& builder)
 | 
	
		
			
				|  |  | +llvm::Value* ExpressionCodegenVisitor::visit(sem::UnaryOperation& unop, llvm::IRBuilder<>& builder)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      using llvm::Value;
 | 
	
		
			
				|  |  | -    auto [value, type] = unop.arg->accept(*this, builder);
 | 
	
		
			
				|  |  | +    auto value = unop.arg->accept(*this, builder);
 | 
	
		
			
				|  |  | +    auto& type = unop.arg->type;
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  | -    if (type != sem::Type::INTEGER)
 | 
	
		
			
				|  |  | +    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"), sem::Type::INTEGER };
 | 
	
		
			
				|  |  | +            return builder.CreateNeg(value, "negate");
 | 
	
		
			
				|  |  |          case ast::Operation::Operator::NOT:
 | 
	
		
			
				|  |  | -            return { builder.CreateNot(value, "not"), sem::Type::BOOLEAN };
 | 
	
		
			
				|  |  | +            return builder.CreateNot(value, "not");
 | 
	
		
			
				|  |  |          default:
 | 
	
		
			
				|  |  |              throw "operator not supported";
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -std::pair<llvm::Value*, sem::Type*> ExpressionCodegenVisitor::visit(sem::NewArrayExpression& naexpr, llvm::IRBuilder<>& builder)
 | 
	
		
			
				|  |  | +llvm::Value* ExpressionCodegenVisitor::visit(sem::NewArrayExpression& naexpr, llvm::IRBuilder<>& builder)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      using llvm::Value;
 | 
	
		
			
				|  |  |      // TODO implement
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -std::pair<llvm::Value*, sem::Type*> ExpressionCodegenVisitor::visit(sem::FeatureCallExpression& call, llvm::IRBuilder<>& builder)
 | 
	
		
			
				|  |  | +llvm::Value* ExpressionCodegenVisitor::visit(sem::FeatureCallExpression& call, llvm::IRBuilder<>& builder)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      using llvm::Value;
 | 
	
		
			
				|  |  |      std::vector<Value*> arguments;
 | 
	
	
		
			
				|  | @@ -109,9 +112,9 @@ std::pair<llvm::Value*, sem::Type*> ExpressionCodegenVisitor::visit(sem::Feature
 | 
	
		
			
				|  |  |      for (size_t i = 0; i < call.arguments.size(); i++) {
 | 
	
		
			
				|  |  |          // : call.arguments) {
 | 
	
		
			
				|  |  |          auto& arg = call.arguments[i];
 | 
	
		
			
				|  |  | -        auto [value, type] = arg->accept(*this, builder);
 | 
	
		
			
				|  |  | +        auto value = arg->accept(*this, builder);
 | 
	
		
			
				|  |  |          
 | 
	
		
			
				|  |  | -        if (!type->equals(*call.callee->arguments[i]->type.get())) {
 | 
	
		
			
				|  |  | +        if (!arg->type->equals(*call.callee->arguments[i]->type.get())) {
 | 
	
		
			
				|  |  |              throw "argument type mismatch";
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          
 | 
	
	
		
			
				|  | @@ -120,16 +123,13 @@ std::pair<llvm::Value*, sem::Type*> ExpressionCodegenVisitor::visit(sem::Feature
 | 
	
		
			
				|  |  |      auto returnType = call.callee->returnType;
 | 
	
		
			
				|  |  |      llvm::CallInst* callInst = builder.CreateCall(call.callee->llvmNode, arguments);
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  | -    return { callInst, returnType.get() };
 | 
	
		
			
				|  |  | -    //return { nullptr, sem::Type::NULL_TYPE };
 | 
	
		
			
				|  |  | +    return callInst;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -std::pair<llvm::Value*, sem::Type*> ExpressionCodegenVisitor::visit(sem::IntConst& node, llvm::IRBuilder<>& builder)
 | 
	
		
			
				|  |  | +llvm::Value* ExpressionCodegenVisitor::visit(sem::IntConst& node, llvm::IRBuilder<>& builder)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -    return {
 | 
	
		
			
				|  |  | -        llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, std::to_string(node.value), 10)),
 | 
	
		
			
				|  |  | -        sem::Type::INTEGER
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | +    return llvm::ConstantInt::get(builder.getContext(),
 | 
	
		
			
				|  |  | +        llvm::APInt(32, std::to_string(node.value), 10));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -151,7 +151,7 @@ llvm::Value* StatementVisitor::visit(sem::IfElseBlock& ifElseBlock,
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  |      llvm::IRBuilder<> builder(fg.getContext());
 | 
	
		
			
				|  |  |      builder.SetInsertPoint(fg.getCurrentBlock());
 | 
	
		
			
				|  |  | -    auto [condition, condType] = ifElseBlock.condition->accept(fg.expressionVisitor, builder);
 | 
	
		
			
				|  |  | +    auto condition = ifElseBlock.condition->accept(fg.expressionVisitor, builder);
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  |      llvm::Function* function = fg.getCurrentBlock()->getParent();
 | 
	
		
			
				|  |  |      
 | 
	
	
		
			
				|  | @@ -200,7 +200,7 @@ llvm::Value* StatementVisitor::visit(sem::WhileBlock& whileBlock,
 | 
	
		
			
				|  |  |      builder.CreateBr(startloop);
 | 
	
		
			
				|  |  |      fg.pushBlock(startloop);
 | 
	
		
			
				|  |  |      builder.SetInsertPoint(startloop);
 | 
	
		
			
				|  |  | -    auto [condition, condType] = whileBlock.condition->accept(fg.expressionVisitor, builder);
 | 
	
		
			
				|  |  | +    auto condition = whileBlock.condition->accept(fg.expressionVisitor, builder);
 | 
	
		
			
				|  |  |      Value* boolCond = builder.CreateIntCast(condition, llvm::Type::getInt1Ty(fg.getContext()), false);
 | 
	
		
			
				|  |  |      builder.CreateCondBr(condition, body, merge);
 | 
	
		
			
				|  |  |      fg.popBlock();
 | 
	
	
		
			
				|  | @@ -220,7 +220,7 @@ llvm::Value* StatementVisitor::visit(sem::AssignmentStatement& assignment,
 | 
	
		
			
				|  |  |      Logger& logger = Logger::getInstance();
 | 
	
		
			
				|  |  |      llvm::IRBuilder<> builder(fg.getContext());
 | 
	
		
			
				|  |  |      builder.SetInsertPoint(fg.getCurrentBlock());
 | 
	
		
			
				|  |  | -    auto [val, type] = assignment.value->accept(fg.expressionVisitor, builder);
 | 
	
		
			
				|  |  | +    auto val = assignment.value->accept(fg.expressionVisitor, builder);
 | 
	
		
			
				|  |  |      if (auto* targetVar =
 | 
	
		
			
				|  |  |          dynamic_cast<sem::LocalVariableExpression*>(assignment.target.get()); targetVar) {
 | 
	
		
			
				|  |  |          logger.debug() << "assigning to LocalVariableExpression" << std::endl;
 | 
	
	
		
			
				|  | @@ -247,7 +247,7 @@ llvm::Value* StatementVisitor::visit(sem::ReturnStatement& returnStatement,
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      llvm::IRBuilder<> builder(fg.getContext());
 | 
	
		
			
				|  |  |      builder.SetInsertPoint(fg.getCurrentBlock());
 | 
	
		
			
				|  |  | -    auto [val, type] = returnStatement.value->accept(fg.expressionVisitor, builder);
 | 
	
		
			
				|  |  | +    auto val = returnStatement.value->accept(fg.expressionVisitor, builder);
 | 
	
		
			
				|  |  |      builder.CreateRet(val);
 | 
	
		
			
				|  |  |      return val;
 | 
	
		
			
				|  |  |  }
 |